github.com/swisscom/cloudfoundry-cli@v7.1.0+incompatible/api/cloudcontroller/ccv3/deployment_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/constant" 9 10 . "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3" 11 . "github.com/onsi/ginkgo" 12 . "github.com/onsi/gomega" 13 . "github.com/onsi/gomega/ghttp" 14 ) 15 16 var _ = Describe("Task", func() { 17 var client *Client 18 19 BeforeEach(func() { 20 client, _ = NewTestClient() 21 }) 22 23 Describe("GetDeployments", func() { 24 var ( 25 deployments []Deployment 26 warnings Warnings 27 executeErr error 28 ) 29 30 JustBeforeEach(func() { 31 deployments, warnings, executeErr = client.GetDeployments(Query{Key: AppGUIDFilter, Values: []string{"some-app-guid"}}, Query{Key: OrderBy, Values: []string{"-created_at"}}, Query{Key: PerPage, Values: []string{"1"}}) 32 }) 33 34 var response string 35 var response2 string 36 BeforeEach(func() { 37 response = fmt.Sprintf(`{ 38 "pagination": { 39 "next": { 40 "href": "%s/v3/deployments?app_guids=some-app-guid&order_by=-created_at&page=2&per_page=1" 41 } 42 }, 43 "resources": [ 44 { 45 "guid": "newest-deployment-guid", 46 "created_at": "2018-05-25T22:42:10Z" 47 } 48 ] 49 }`, server.URL()) 50 response2 = `{ 51 "pagination": { 52 "next": null 53 }, 54 "resources": [ 55 { 56 "guid": "oldest-deployment-guid", 57 "created_at": "2018-04-25T22:42:10Z" 58 } 59 ] 60 }` 61 }) 62 63 Context("when the deployment exists", func() { 64 BeforeEach(func() { 65 server.AppendHandlers( 66 CombineHandlers( 67 VerifyRequest(http.MethodGet, "/v3/deployments", "app_guids=some-app-guid&order_by=-created_at&per_page=1"), 68 RespondWith(http.StatusAccepted, response), 69 ), 70 ) 71 72 server.AppendHandlers( 73 CombineHandlers( 74 VerifyRequest(http.MethodGet, "/v3/deployments", "app_guids=some-app-guid&order_by=-created_at&page=2&per_page=1"), 75 RespondWith(http.StatusAccepted, response2, http.Header{"X-Cf-Warnings": {"warning"}}), 76 ), 77 ) 78 79 }) 80 81 It("returns the deployment guid of the most recent deployment", func() { 82 Expect(executeErr).ToNot(HaveOccurred()) 83 Expect(warnings).To(ConsistOf("warning")) 84 Expect(deployments).To(ConsistOf( 85 Deployment{GUID: "newest-deployment-guid", CreatedAt: "2018-05-25T22:42:10Z"}, 86 Deployment{GUID: "oldest-deployment-guid", CreatedAt: "2018-04-25T22:42:10Z"}, 87 )) 88 }) 89 90 }) 91 92 Context("when the request fails", func() { 93 BeforeEach(func() { 94 response := `{ 95 "errors": [ 96 { 97 "code": 10008, 98 "detail": "The request is semantically invalid: command presence", 99 "title": "CF-UnprocessableEntity" 100 }, 101 { 102 "code": 10010, 103 "detail": "App not found", 104 "title": "CF-ResourceNotFound" 105 } 106 ] 107 }` 108 109 server.AppendHandlers( 110 CombineHandlers( 111 VerifyRequest(http.MethodGet, "/v3/deployments", "app_guids=some-app-guid&order_by=-created_at&per_page=1"), 112 RespondWith(http.StatusTeapot, response, http.Header{"X-Cf-Warnings": {"warning"}}), 113 ), 114 ) 115 }) 116 117 It("returns CC warnings and error", func() { 118 Expect(executeErr).To(MatchError(ccerror.MultiError{ 119 ResponseCode: http.StatusTeapot, 120 Errors: []ccerror.V3Error{ 121 { 122 Code: 10008, 123 Detail: "The request is semantically invalid: command presence", 124 Title: "CF-UnprocessableEntity", 125 }, 126 { 127 Code: 10010, 128 Detail: "App not found", 129 Title: "CF-ResourceNotFound", 130 }, 131 }, 132 })) 133 Expect(warnings).To(ConsistOf("warning")) 134 }) 135 }) 136 }) 137 138 Describe("CancelDeployment", func() { 139 var ( 140 warnings Warnings 141 executeErr error 142 ) 143 144 JustBeforeEach(func() { 145 warnings, executeErr = client.CancelDeployment("some-deployment-guid") 146 }) 147 148 Context("when the deployment exists", func() { 149 Context("when cancelling the deployment succeeds", func() { 150 BeforeEach(func() { 151 server.AppendHandlers( 152 CombineHandlers( 153 VerifyRequest(http.MethodPost, "/v3/deployments/some-deployment-guid/actions/cancel"), 154 RespondWith(http.StatusAccepted, "", http.Header{"X-Cf-Warnings": {"warning"}}), 155 ), 156 ) 157 }) 158 159 It("cancels the deployment with no errors and returns all warnings", func() { 160 Expect(executeErr).ToNot(HaveOccurred()) 161 Expect(warnings).To(ConsistOf("warning")) 162 }) 163 }) 164 }) 165 }) 166 167 Describe("CreateApplicationDeployment", func() { 168 var ( 169 deploymentGUID string 170 warnings Warnings 171 executeErr error 172 dropletGUID string 173 ) 174 175 JustBeforeEach(func() { 176 deploymentGUID, warnings, executeErr = client.CreateApplicationDeployment("some-app-guid", dropletGUID) 177 }) 178 179 Context("when the application exists", func() { 180 var response string 181 BeforeEach(func() { 182 dropletGUID = "some-droplet-guid" 183 response = `{ 184 "guid": "some-deployment-guid", 185 "created_at": "2018-04-25T22:42:10Z", 186 "relationships": { 187 "app": { 188 "data": { 189 "guid": "some-app-guid" 190 } 191 } 192 } 193 }` 194 }) 195 196 Context("when creating the deployment succeeds", func() { 197 BeforeEach(func() { 198 server.AppendHandlers( 199 CombineHandlers( 200 VerifyRequest(http.MethodPost, "/v3/deployments"), 201 VerifyJSON(`{"droplet":{ "guid":"some-droplet-guid" }, "relationships":{"app":{"data":{"guid":"some-app-guid"}}}}`), 202 RespondWith(http.StatusAccepted, response, http.Header{"X-Cf-Warnings": {"warning"}}), 203 ), 204 ) 205 }) 206 207 It("creates the deployment with no errors and returns all warnings", func() { 208 Expect(deploymentGUID).To(Equal("some-deployment-guid")) 209 Expect(executeErr).ToNot(HaveOccurred()) 210 Expect(warnings).To(ConsistOf("warning")) 211 }) 212 213 }) 214 215 Context("when no droplet guid is provided", func() { 216 BeforeEach(func() { 217 dropletGUID = "" 218 server.AppendHandlers( 219 CombineHandlers( 220 VerifyRequest(http.MethodPost, "/v3/deployments"), 221 VerifyJSON(`{"relationships":{"app":{"data":{"guid":"some-app-guid"}}}}`), 222 RespondWith(http.StatusAccepted, response, http.Header{"X-Cf-Warnings": {"warning"}}), 223 ), 224 ) 225 }) 226 227 It("omits the droplet object in the JSON", func() { 228 Expect(executeErr).ToNot(HaveOccurred()) 229 Expect(warnings).To(ConsistOf("warning")) 230 }) 231 }) 232 }) 233 }) 234 235 Describe("CreateApplicationDeploymentByRevision", func() { 236 var ( 237 deploymentGUID string 238 warnings Warnings 239 executeErr error 240 revisionGUID string 241 ) 242 243 JustBeforeEach(func() { 244 deploymentGUID, warnings, executeErr = client.CreateApplicationDeploymentByRevision("some-app-guid", revisionGUID) 245 }) 246 247 Context("when the application exists", func() { 248 var response string 249 BeforeEach(func() { 250 revisionGUID = "some-revision-guid" 251 response = `{ 252 "guid": "some-deployment-guid", 253 "created_at": "2018-04-25T22:42:10Z", 254 "relationships": { 255 "app": { 256 "data": { 257 "guid": "some-app-guid" 258 } 259 } 260 } 261 }` 262 }) 263 264 Context("when creating the deployment succeeds", func() { 265 BeforeEach(func() { 266 server.AppendHandlers( 267 CombineHandlers( 268 VerifyRequest(http.MethodPost, "/v3/deployments"), 269 VerifyJSON(`{"revision":{ "guid":"some-revision-guid" }, "relationships":{"app":{"data":{"guid":"some-app-guid"}}}}`), 270 RespondWith(http.StatusAccepted, response, http.Header{"X-Cf-Warnings": {"warning"}}), 271 ), 272 ) 273 }) 274 275 It("creates the deployment with no errors and returns all warnings", func() { 276 Expect(deploymentGUID).To(Equal("some-deployment-guid")) 277 Expect(executeErr).ToNot(HaveOccurred()) 278 Expect(warnings).To(ConsistOf("warning")) 279 }) 280 }) 281 }) 282 }) 283 284 Describe("GetDeployment", func() { 285 var response string 286 Context("When the deployments exists", func() { 287 BeforeEach(func() { 288 response = `{ 289 "guid": "some-deployment-guid", 290 "state": "DEPLOYED", 291 "status": { 292 "value": "FINALIZED", 293 "reason": "SUPERSEDED" 294 }, 295 "droplet": { 296 "guid": "some-droplet-guid" 297 }, 298 "previous_droplet": { 299 "guid": "some-other-droplet-guid" 300 }, 301 "created_at": "some-time", 302 "updated_at": "some-later-time", 303 "relationships": { 304 "app": { 305 "data": { 306 "guid": "some-app-guid" 307 } 308 } 309 } 310 }` 311 server.AppendHandlers( 312 CombineHandlers( 313 VerifyRequest(http.MethodGet, "/v3/deployments/some-deployment-guid"), 314 RespondWith(http.StatusAccepted, response, http.Header{"X-Cf-Warnings": {"warning"}}), 315 ), 316 ) 317 }) 318 It("Successfully returns a deployment object", func() { 319 deployment, warnings, err := client.GetDeployment("some-deployment-guid") 320 Expect(err).ToNot(HaveOccurred()) 321 Expect(warnings).To(ConsistOf("warning")) 322 Expect(deployment).To(Not(BeNil())) 323 Expect(deployment.GUID).To(Equal("some-deployment-guid")) 324 Expect(deployment.State).To(Equal(constant.DeploymentDeployed)) 325 Expect(deployment.StatusValue).To(Equal(constant.DeploymentStatusValueFinalized)) 326 Expect(deployment.StatusReason).To(Equal(constant.DeploymentStatusReasonSuperseded)) 327 }) 328 }) 329 330 Context("when the deployment doesn't exist", func() { 331 BeforeEach(func() { 332 response := `{ 333 "errors": [ 334 { 335 "code": 10010, 336 "detail": "Deployment not found", 337 "title": "CF-ResourceNotFound" 338 } 339 ] 340 }` 341 server.AppendHandlers( 342 CombineHandlers( 343 VerifyRequest(http.MethodGet, "/v3/deployments/not-a-deployment"), 344 RespondWith(http.StatusNotFound, response, http.Header{"X-Cf-Warnings": {"warning-deployment"}}), 345 ), 346 ) 347 }) 348 349 It("returns the error", func() { 350 _, warnings, err := client.GetDeployment("not-a-deployment") 351 Expect(err).To(MatchError(ccerror.DeploymentNotFoundError{})) 352 Expect(warnings).To(ConsistOf("warning-deployment")) 353 }) 354 }) 355 }) 356 })