github.com/loafoe/cli@v7.1.0+incompatible/cf/api/buildpacks_test.go (about) 1 package api_test 2 3 import ( 4 "net/http" 5 "net/http/httptest" 6 "time" 7 8 . "code.cloudfoundry.org/cli/cf/api" 9 "code.cloudfoundry.org/cli/cf/api/apifakes" 10 "code.cloudfoundry.org/cli/cf/configuration/coreconfig" 11 "code.cloudfoundry.org/cli/cf/errors" 12 "code.cloudfoundry.org/cli/cf/models" 13 "code.cloudfoundry.org/cli/cf/net" 14 "code.cloudfoundry.org/cli/cf/terminal/terminalfakes" 15 "code.cloudfoundry.org/cli/cf/trace/tracefakes" 16 testconfig "code.cloudfoundry.org/cli/cf/util/testhelpers/configuration" 17 . "code.cloudfoundry.org/cli/cf/util/testhelpers/matchers" 18 testnet "code.cloudfoundry.org/cli/cf/util/testhelpers/net" 19 . "github.com/onsi/ginkgo" 20 . "github.com/onsi/gomega" 21 ) 22 23 var _ = Describe("Buildpacks repo", func() { 24 var ( 25 ts *httptest.Server 26 handler *testnet.TestHandler 27 config coreconfig.ReadWriter 28 repo BuildpackRepository 29 ) 30 31 BeforeEach(func() { 32 config = testconfig.NewRepositoryWithDefaults() 33 gateway := net.NewCloudControllerGateway(config, time.Now, new(terminalfakes.FakeUI), new(tracefakes.FakePrinter), "") 34 repo = NewCloudControllerBuildpackRepository(config, gateway) 35 }) 36 37 AfterEach(func() { 38 ts.Close() 39 }) 40 41 var setupTestServer = func(requests ...testnet.TestRequest) { 42 ts, handler = testnet.NewServer(requests) 43 config.SetAPIEndpoint(ts.URL) 44 } 45 46 It("lists buildpacks", func() { 47 setupTestServer( 48 apifakes.NewCloudControllerTestRequest(testnet.TestRequest{ 49 Method: "GET", 50 Path: "/v2/buildpacks", 51 Response: testnet.TestResponse{ 52 Status: http.StatusOK, 53 Body: `{ 54 "next_url": "/v2/buildpacks?page=2", 55 "resources": [ 56 { 57 "metadata": { 58 "guid": "buildpack1-guid" 59 }, 60 "entity": { 61 "name": "Buildpack1", 62 "position" : 1, 63 "filename" : "firstbp.zip" 64 } 65 } 66 ] 67 }`}}), 68 apifakes.NewCloudControllerTestRequest(testnet.TestRequest{ 69 Method: "GET", 70 Path: "/v2/buildpacks?page=2", 71 Response: testnet.TestResponse{ 72 Status: http.StatusOK, 73 Body: `{ 74 "resources": [ 75 { 76 "metadata": { 77 "guid": "buildpack2-guid" 78 }, 79 "entity": { 80 "name": "Buildpack2", 81 "position" : 2 82 } 83 } 84 ] 85 }`}, 86 })) 87 88 buildpacks := []models.Buildpack{} 89 err := repo.ListBuildpacks(func(b models.Buildpack) bool { 90 buildpacks = append(buildpacks, b) 91 return true 92 }) 93 94 one := 1 95 two := 2 96 Expect(buildpacks).To(ConsistOf([]models.Buildpack{ 97 { 98 GUID: "buildpack1-guid", 99 Name: "Buildpack1", 100 Position: &one, 101 Filename: "firstbp.zip", 102 }, 103 { 104 GUID: "buildpack2-guid", 105 Name: "Buildpack2", 106 Position: &two, 107 }, 108 })) 109 Expect(handler).To(HaveAllRequestsCalled()) 110 Expect(err).NotTo(HaveOccurred()) 111 }) 112 113 Describe("finding buildpacks by name", func() { 114 It("returns the buildpack with that name", func() { 115 setupTestServer(apifakes.NewCloudControllerTestRequest(testnet.TestRequest{ 116 Method: "GET", 117 Path: "/v2/buildpacks?q=name%3ABuildpack1", 118 Response: testnet.TestResponse{ 119 Status: http.StatusOK, 120 Body: `{"resources": [ 121 { 122 "metadata": { 123 "guid": "buildpack1-guid" 124 }, 125 "entity": { 126 "name": "Buildpack1", 127 "position": 10 128 } 129 } 130 ] 131 }`}})) 132 133 buildpack, apiErr := repo.FindByName("Buildpack1") 134 135 Expect(handler).To(HaveAllRequestsCalled()) 136 Expect(apiErr).NotTo(HaveOccurred()) 137 138 Expect(buildpack.Name).To(Equal("Buildpack1")) 139 Expect(buildpack.GUID).To(Equal("buildpack1-guid")) 140 Expect(*buildpack.Position).To(Equal(10)) 141 }) 142 143 It("returns a ModelNotFoundError when the buildpack is not found", func() { 144 setupTestServer(apifakes.NewCloudControllerTestRequest(testnet.TestRequest{ 145 Method: "GET", 146 Path: "/v2/buildpacks?q=name%3ABuildpack1", 147 Response: testnet.TestResponse{ 148 Status: http.StatusOK, 149 Body: `{"resources": []}`, 150 }, 151 })) 152 153 _, apiErr := repo.FindByName("Buildpack1") 154 Expect(handler).To(HaveAllRequestsCalled()) 155 Expect(apiErr.(*errors.ModelNotFoundError)).NotTo(BeNil()) 156 }) 157 158 It("returns a AmbiguousModelError when more than one buildpack with the same name exists", func() { 159 setupTestServer(apifakes.NewCloudControllerTestRequest(testnet.TestRequest{ 160 Method: "GET", 161 Path: "/v2/buildpacks?q=name%3ABuildpack1", 162 Response: testnet.TestResponse{ 163 Status: http.StatusOK, 164 Body: `{"resources": [ 165 { 166 "metadata": { 167 "guid": "buildpack1-guid" 168 }, 169 "entity": { 170 "name": "Buildpack1", 171 "stack": "Stack1", 172 "position": 10 173 } 174 }, 175 { 176 "metadata": { 177 "guid": "buildpack1-guid2" 178 }, 179 "entity": { 180 "name": "Buildpack1", 181 "stack": "Stack2", 182 "position": 11 183 } 184 } 185 ] 186 }`}, 187 })) 188 189 _, apiErr := repo.FindByName("Buildpack1") 190 Expect(handler).To(HaveAllRequestsCalled()) 191 Expect(apiErr).To(BeAssignableToTypeOf(&errors.AmbiguousModelError{})) 192 }) 193 }) 194 195 Describe("finding buildpacks by name and stack", func() { 196 It("returns the buildpack with that name and stack", func() { 197 setupTestServer(apifakes.NewCloudControllerTestRequest(testnet.TestRequest{ 198 Method: "GET", 199 Path: "/v2/buildpacks?q=name%3ABuildpack1%3Bstack%3AStack1", 200 Response: testnet.TestResponse{ 201 Status: http.StatusOK, 202 Body: `{"resources": [ 203 { 204 "metadata": { 205 "guid": "buildpack1-guid" 206 }, 207 "entity": { 208 "name": "Buildpack1", 209 "stack": "Stack1", 210 "position": 10 211 } 212 } 213 ] 214 }`}})) 215 216 buildpack, apiErr := repo.FindByNameAndStack("Buildpack1", "Stack1") 217 218 Expect(handler).To(HaveAllRequestsCalled()) 219 Expect(apiErr).NotTo(HaveOccurred()) 220 221 Expect(buildpack.Name).To(Equal("Buildpack1")) 222 Expect(buildpack.Stack).To(Equal("Stack1")) 223 Expect(buildpack.GUID).To(Equal("buildpack1-guid")) 224 Expect(*buildpack.Position).To(Equal(10)) 225 }) 226 227 It("returns a ModelNotFoundError when the buildpack is not found", func() { 228 setupTestServer(apifakes.NewCloudControllerTestRequest(testnet.TestRequest{ 229 Method: "GET", 230 Path: "/v2/buildpacks?q=name%3ABuildpack1%3Bstack%3AStack1", 231 Response: testnet.TestResponse{ 232 Status: http.StatusOK, 233 Body: `{"resources": []}`, 234 }, 235 })) 236 237 _, apiErr := repo.FindByNameAndStack("Buildpack1", "Stack1") 238 Expect(handler).To(HaveAllRequestsCalled()) 239 Expect(apiErr.(*errors.ModelNotFoundError)).NotTo(BeNil()) 240 }) 241 }) 242 243 Describe("creating buildpacks", func() { 244 It("returns an error when the buildpack has an invalid name", func() { 245 setupTestServer(testnet.TestRequest{ 246 Method: "POST", 247 Path: "/v2/buildpacks", 248 Response: testnet.TestResponse{ 249 Status: http.StatusBadRequest, 250 Body: `{ 251 "code":290003, 252 "description":"Buildpack is invalid: [\"name can only contain alphanumeric characters\"]", 253 "error_code":"CF-BuildpackInvalid" 254 }`, 255 }}) 256 257 one := 1 258 createdBuildpack, apiErr := repo.Create("name with space", &one, nil, nil) 259 Expect(apiErr).To(HaveOccurred()) 260 Expect(createdBuildpack).To(Equal(models.Buildpack{})) 261 Expect(apiErr.(errors.HTTPError).ErrorCode()).To(Equal("290003")) 262 Expect(apiErr.Error()).To(ContainSubstring("Buildpack is invalid")) 263 }) 264 265 It("sets the position flag when creating a buildpack", func() { 266 setupTestServer(apifakes.NewCloudControllerTestRequest(testnet.TestRequest{ 267 Method: "POST", 268 Path: "/v2/buildpacks", 269 Matcher: testnet.RequestBodyMatcher(`{"name":"my-cool-buildpack","position":999}`), 270 Response: testnet.TestResponse{ 271 Status: http.StatusCreated, 272 Body: `{ 273 "metadata": { 274 "guid": "my-cool-buildpack-guid" 275 }, 276 "entity": { 277 "name": "my-cool-buildpack", 278 "position":999 279 } 280 }`}, 281 })) 282 283 position := 999 284 created, apiErr := repo.Create("my-cool-buildpack", &position, nil, nil) 285 286 Expect(handler).To(HaveAllRequestsCalled()) 287 Expect(apiErr).NotTo(HaveOccurred()) 288 289 Expect(created.GUID).NotTo(BeNil()) 290 Expect("my-cool-buildpack").To(Equal(created.Name)) 291 Expect(999).To(Equal(*created.Position)) 292 }) 293 294 It("sets the enabled flag when creating a buildpack", func() { 295 setupTestServer(apifakes.NewCloudControllerTestRequest(testnet.TestRequest{ 296 Method: "POST", 297 Path: "/v2/buildpacks", 298 Matcher: testnet.RequestBodyMatcher(`{"name":"my-cool-buildpack","position":999, "enabled":true}`), 299 Response: testnet.TestResponse{ 300 Status: http.StatusCreated, 301 Body: `{ 302 "metadata": { 303 "guid": "my-cool-buildpack-guid" 304 }, 305 "entity": { 306 "name": "my-cool-buildpack", 307 "position":999, 308 "enabled":true 309 } 310 }`}, 311 })) 312 313 position := 999 314 enabled := true 315 created, apiErr := repo.Create("my-cool-buildpack", &position, &enabled, nil) 316 317 Expect(handler).To(HaveAllRequestsCalled()) 318 Expect(apiErr).NotTo(HaveOccurred()) 319 320 Expect(created.GUID).NotTo(BeNil()) 321 Expect(created.Name).To(Equal("my-cool-buildpack")) 322 Expect(999).To(Equal(*created.Position)) 323 }) 324 }) 325 326 It("deletes buildpacks", func() { 327 setupTestServer(apifakes.NewCloudControllerTestRequest(testnet.TestRequest{ 328 Method: "DELETE", 329 Path: "/v2/buildpacks/my-cool-buildpack-guid", 330 Response: testnet.TestResponse{ 331 Status: http.StatusNoContent, 332 }})) 333 334 err := repo.Delete("my-cool-buildpack-guid") 335 336 Expect(handler).To(HaveAllRequestsCalled()) 337 Expect(err).NotTo(HaveOccurred()) 338 }) 339 340 Describe("updating buildpacks", func() { 341 It("updates a buildpack's name, position and enabled flag", func() { 342 setupTestServer(apifakes.NewCloudControllerTestRequest(testnet.TestRequest{ 343 Method: "PUT", 344 Path: "/v2/buildpacks/my-cool-buildpack-guid", 345 Matcher: testnet.RequestBodyMatcher(`{"name":"my-cool-buildpack","position":555,"enabled":false}`), 346 Response: testnet.TestResponse{ 347 Status: http.StatusCreated, 348 Body: `{ 349 "metadata": { 350 "guid": "my-cool-buildpack-guid" 351 }, 352 "entity": { 353 "name": "my-cool-buildpack", 354 "position":555, 355 "enabled":false 356 } 357 }`}, 358 })) 359 360 position := 555 361 enabled := false 362 buildpack := models.Buildpack{ 363 Name: "my-cool-buildpack", 364 GUID: "my-cool-buildpack-guid", 365 Position: &position, 366 Enabled: &enabled, 367 } 368 369 updated, err := repo.Update(buildpack) 370 371 Expect(handler).To(HaveAllRequestsCalled()) 372 Expect(err).NotTo(HaveOccurred()) 373 Expect(updated).To(Equal(buildpack)) 374 }) 375 376 It("sets the locked attribute on the buildpack", func() { 377 setupTestServer(apifakes.NewCloudControllerTestRequest(testnet.TestRequest{ 378 Method: "PUT", 379 Path: "/v2/buildpacks/my-cool-buildpack-guid", 380 Matcher: testnet.RequestBodyMatcher(`{"name":"my-cool-buildpack","locked":true}`), 381 Response: testnet.TestResponse{ 382 Status: http.StatusCreated, 383 Body: `{ 384 385 "metadata": { 386 "guid": "my-cool-buildpack-guid" 387 }, 388 "entity": { 389 "name": "my-cool-buildpack", 390 "position":123, 391 "locked": true 392 } 393 }`}, 394 })) 395 396 locked := true 397 398 buildpack := models.Buildpack{ 399 Name: "my-cool-buildpack", 400 GUID: "my-cool-buildpack-guid", 401 Locked: &locked, 402 } 403 404 updated, err := repo.Update(buildpack) 405 406 Expect(handler).To(HaveAllRequestsCalled()) 407 Expect(err).NotTo(HaveOccurred()) 408 409 position := 123 410 Expect(updated).To(Equal(models.Buildpack{ 411 Name: "my-cool-buildpack", 412 GUID: "my-cool-buildpack-guid", 413 Position: &position, 414 Locked: &locked, 415 })) 416 }) 417 }) 418 })