gopkg.in/goose.v2@v2.0.1/cinder/client_test.go (about) 1 // Copyright 2015 Canonical Ltd. 2 // Licensed under the LGPLv3, see LICENCE file for details. 3 4 package cinder 5 6 import ( 7 "bytes" 8 "encoding/json" 9 "fmt" 10 "io/ioutil" 11 "net/http" 12 "net/url" 13 14 gc "gopkg.in/check.v1" 15 ) 16 17 const ( 18 testId = "test-id" 19 testToken = "test-token" 20 testTime = "test-time" 21 testDescr = "test-description" 22 testName = "test-name" 23 testAttrProgr = "test-attribute-prog" 24 testAttrProj = "test-attribute-proj" 25 testStatus = "test-status" 26 ) 27 28 var _ = gc.Suite(&CinderTestSuite{}) 29 30 type CinderTestSuite struct { 31 client *Client 32 *http.ServeMux 33 } 34 35 func (s *CinderTestSuite) SetUpSuite(c *gc.C) { 36 37 if *live { 38 return 39 } 40 41 endpoint, err := url.Parse("http://volume.testing/v2/" + testId) 42 c.Assert(err, gc.IsNil) 43 44 cinderClient := NewClient( 45 testId, 46 endpoint, 47 SetAuthHeaderFn(func() string { return testToken }, s.localDo), 48 ) 49 s.client = cinderClient 50 } 51 52 func (s *CinderTestSuite) SetUpTest(c *gc.C) { 53 54 if *live { 55 c.Skip("Only running live tests.") 56 } 57 58 // We want a fresh Muxer so that any paths that aren't explicitly 59 // set up by the test are treated as errors. 60 s.ServeMux = http.NewServeMux() 61 } 62 63 func (s *CinderTestSuite) TestCreateSnapshot(c *gc.C) { 64 65 snapReq := CreateSnapshotSnapshotParams{ 66 VolumeId: testId, 67 Name: testName, 68 Description: testDescr, 69 } 70 71 numCalls := 0 72 s.HandleFunc("/v2/"+testId+"/snapshots", func(w http.ResponseWriter, req *http.Request) { 73 numCalls++ 74 75 c.Check(req.Header["X-Auth-Token"], gc.DeepEquals, []string{testToken}) 76 77 reqBody, err := ioutil.ReadAll(req.Body) 78 c.Assert(err, gc.IsNil) 79 80 var receivedReq CreateSnapshotParams 81 err = json.Unmarshal(reqBody, &receivedReq) 82 c.Assert(err, gc.IsNil) 83 84 c.Check(receivedReq, gc.DeepEquals, CreateSnapshotParams{Snapshot: snapReq}) 85 86 resp := Snapshot{ 87 CreatedAt: "test-time", 88 Description: receivedReq.Snapshot.Description, 89 ID: "test-id", 90 Name: receivedReq.Snapshot.Name, 91 Size: 1, 92 Status: "test-status", 93 VolumeID: receivedReq.Snapshot.VolumeId, 94 } 95 respBody, err := json.Marshal(&CreateSnapshotResults{Snapshot: resp}) 96 c.Assert(err, gc.IsNil) 97 98 w.(*responseWriter).Body = ioutil.NopCloser(bytes.NewReader(respBody)) 99 w.(*responseWriter).StatusCode = 202 100 }) 101 102 resp, err := s.client.CreateSnapshot(snapReq) 103 c.Assert(numCalls, gc.Equals, 1) 104 c.Assert(err, gc.IsNil) 105 106 c.Check(resp.Snapshot.CreatedAt, gc.Equals, testTime) 107 c.Check(resp.Snapshot.Description, gc.Equals, snapReq.Description) 108 c.Check(resp.Snapshot.ID, gc.Equals, testId) 109 c.Check(resp.Snapshot.Name, gc.Equals, snapReq.Name) 110 c.Check(resp.Snapshot.Size, gc.Equals, 1) 111 c.Check(resp.Snapshot.Status, gc.Equals, testStatus) 112 c.Check(resp.Snapshot.VolumeID, gc.Equals, snapReq.VolumeId) 113 114 } 115 116 func (s *CinderTestSuite) TestDeleteSnapshot(c *gc.C) { 117 numCalls := 0 118 s.HandleFunc("/v2/"+testId+"/snapshots/"+testId, func(w http.ResponseWriter, req *http.Request) { 119 numCalls++ 120 121 w.(*responseWriter).Body = ioutil.NopCloser(bytes.NewReader([]byte{})) 122 w.(*responseWriter).StatusCode = 202 123 }) 124 125 err := s.client.DeleteSnapshot(testId) 126 c.Assert(numCalls, gc.Equals, 1) 127 c.Assert(err, gc.IsNil) 128 } 129 130 func (s *CinderTestSuite) TestGetSnapshot(c *gc.C) { 131 132 numCalls := 0 133 s.HandleFunc("/v2/"+testId+"/snapshots/"+testId, func(w http.ResponseWriter, req *http.Request) { 134 numCalls++ 135 136 c.Check(req.Header["X-Auth-Token"], gc.DeepEquals, []string{testToken}) 137 138 resp := Snapshot{ 139 CreatedAt: testTime, 140 Description: testDescr, 141 ID: testId, 142 Name: testName, 143 Os_Extended_Snapshot_Attributes_Progress: testAttrProgr, 144 Os_Extended_Snapshot_Attributes_ProjectID: testAttrProj, 145 Size: 1, 146 Status: testStatus, 147 VolumeID: testId, 148 } 149 150 respBody, err := json.Marshal(&GetSnapshotResults{Snapshot: resp}) 151 c.Assert(err, gc.IsNil) 152 153 w.(*responseWriter).Response.StatusCode = 200 154 w.(*responseWriter).Body = ioutil.NopCloser(bytes.NewReader(respBody)) 155 }) 156 157 // Test GetSnapshot 158 getResp, err := s.client.GetSnapshot(testId) 159 c.Assert(err, gc.IsNil) 160 c.Assert(numCalls, gc.Equals, 1) 161 162 c.Check(getResp.Snapshot.CreatedAt, gc.Not(gc.HasLen), 0) 163 c.Check(getResp.Snapshot.Description, gc.Equals, testDescr) 164 c.Check(getResp.Snapshot.ID, gc.Not(gc.HasLen), 0) 165 c.Check(getResp.Snapshot.Name, gc.Equals, testName) 166 c.Check(getResp.Snapshot.Size, gc.Equals, 1) 167 c.Check(getResp.Snapshot.Status, gc.Equals, testStatus) 168 c.Check(getResp.Snapshot.VolumeID, gc.Equals, testId) 169 } 170 171 func (s *CinderTestSuite) TestGetSnapshotDetail(c *gc.C) { 172 173 numCalls := 0 174 s.HandleFunc("/v2/"+testId+"/snapshots/detail", func(w http.ResponseWriter, req *http.Request) { 175 numCalls++ 176 177 c.Check(req.Header["X-Auth-Token"], gc.DeepEquals, []string{testToken}) 178 179 resp := []Snapshot{{ 180 CreatedAt: testTime, 181 Description: testDescr, 182 ID: testId, 183 Name: testName, 184 Os_Extended_Snapshot_Attributes_Progress: testAttrProgr, 185 Os_Extended_Snapshot_Attributes_ProjectID: testAttrProj, 186 Size: 1, 187 Status: testStatus, 188 VolumeID: testId, 189 }} 190 191 respBody, err := json.Marshal(&GetSnapshotsDetailResults{Snapshots: resp}) 192 c.Assert(err, gc.IsNil) 193 194 w.(*responseWriter).Response.StatusCode = 200 195 w.(*responseWriter).Body = ioutil.NopCloser(bytes.NewReader(respBody)) 196 }) 197 198 detailGetResp, err := s.client.GetSnapshotsDetail() 199 c.Assert(err, gc.IsNil) 200 c.Assert(detailGetResp.Snapshots, gc.HasLen, 1) 201 c.Assert(numCalls, gc.Equals, 1) 202 203 snapshot := detailGetResp.Snapshots[0] 204 205 c.Check(snapshot.CreatedAt, gc.Equals, testTime) 206 c.Check(snapshot.Description, gc.Equals, testDescr) 207 c.Check(snapshot.ID, gc.Equals, testId) 208 c.Check(snapshot.Name, gc.Equals, testName) 209 c.Check(snapshot.Os_Extended_Snapshot_Attributes_Progress, gc.Equals, testAttrProgr) 210 c.Check(snapshot.Os_Extended_Snapshot_Attributes_ProjectID, gc.Equals, testAttrProj) 211 c.Check(snapshot.Size, gc.Equals, 1) 212 c.Check(snapshot.Status, gc.Equals, testStatus) 213 c.Check(snapshot.VolumeID, gc.Equals, testId) 214 } 215 216 func (s *CinderTestSuite) TestGetSnapshotSimple(c *gc.C) { 217 218 numCalls := 0 219 s.HandleFunc("/v2/"+testId+"/snapshots", func(w http.ResponseWriter, req *http.Request) { 220 numCalls++ 221 222 c.Check(req.Header["X-Auth-Token"], gc.DeepEquals, []string{testToken}) 223 224 resp := []Snapshot{{ 225 CreatedAt: testTime, 226 Description: testDescr, 227 ID: testId, 228 Name: testName, 229 Os_Extended_Snapshot_Attributes_Progress: testAttrProgr, 230 Os_Extended_Snapshot_Attributes_ProjectID: testAttrProj, 231 Size: 1, 232 Status: testStatus, 233 VolumeID: testId, 234 }} 235 236 respBody, err := json.Marshal(&GetSnapshotsDetailResults{Snapshots: resp}) 237 c.Assert(err, gc.IsNil) 238 239 w.(*responseWriter).Response.StatusCode = 200 240 w.(*responseWriter).Body = ioutil.NopCloser(bytes.NewReader(respBody)) 241 }) 242 243 snapshotSimpResp, err := s.client.GetSnapshotsSimple() 244 c.Assert(numCalls, gc.Equals, 1) 245 c.Assert(err, gc.IsNil) 246 c.Assert(snapshotSimpResp.Snapshots, gc.HasLen, 1) 247 248 snapshot := snapshotSimpResp.Snapshots[0] 249 250 c.Check(snapshot.CreatedAt, gc.Equals, testTime) 251 c.Check(snapshot.Description, gc.Equals, testDescr) 252 c.Check(snapshot.ID, gc.Equals, testId) 253 c.Check(snapshot.Name, gc.Equals, testName) 254 c.Check(snapshot.Size, gc.Equals, 1) 255 c.Check(snapshot.Status, gc.Equals, testStatus) 256 c.Check(snapshot.VolumeID, gc.Equals, testId) 257 } 258 259 func (s *CinderTestSuite) TestShowSnapshotMetadata(c *gc.C) { 260 261 numCalls := 0 262 s.HandleFunc("/v2/"+testId+"/snapshots/"+testId+"/metadata", func(w http.ResponseWriter, req *http.Request) { 263 numCalls++ 264 265 c.Check(req.Header["X-Auth-Token"], gc.DeepEquals, []string{testToken}) 266 267 resp := Snapshot{ 268 CreatedAt: testTime, 269 Description: testDescr, 270 ID: testId, 271 Name: testName, 272 Os_Extended_Snapshot_Attributes_Progress: testAttrProgr, 273 Os_Extended_Snapshot_Attributes_ProjectID: testAttrProj, 274 Size: 1, 275 Status: testStatus, 276 VolumeID: testId, 277 } 278 279 respBody, err := json.Marshal(&ShowSnapshotMetadataResults{Snapshot: resp}) 280 c.Assert(err, gc.IsNil) 281 282 w.(*responseWriter).Response.StatusCode = 200 283 w.(*responseWriter).Body = ioutil.NopCloser(bytes.NewReader(respBody)) 284 }) 285 286 resp, err := s.client.ShowSnapshotMetadata(testId) 287 c.Assert(err, gc.IsNil) 288 289 c.Check(resp.Snapshot.CreatedAt, gc.Equals, testTime) 290 c.Check(resp.Snapshot.Description, gc.Equals, testDescr) 291 c.Check(resp.Snapshot.ID, gc.Equals, testId) 292 c.Check(resp.Snapshot.Name, gc.Equals, testName) 293 c.Check(resp.Snapshot.Size, gc.Equals, 1) 294 c.Check(resp.Snapshot.Status, gc.Equals, testStatus) 295 c.Check(resp.Snapshot.VolumeID, gc.Equals, testId) 296 } 297 298 func (s *CinderTestSuite) TestUpdateSnapshot(c *gc.C) { 299 300 updateReq := UpdateSnapshotSnapshotParams{testName, testDescr} 301 302 numCalls := 0 303 s.HandleFunc("/v2/"+testId+"/snapshots/"+testId, func(w http.ResponseWriter, req *http.Request) { 304 numCalls++ 305 306 c.Check(req.Header["X-Auth-Token"], gc.DeepEquals, []string{testToken}) 307 308 reqBody, err := ioutil.ReadAll(req.Body) 309 c.Assert(err, gc.IsNil) 310 311 var receivedReq UpdateSnapshotParams 312 err = json.Unmarshal(reqBody, &receivedReq) 313 c.Assert(err, gc.IsNil) 314 315 c.Check(receivedReq, gc.DeepEquals, UpdateSnapshotParams{Snapshot: updateReq}) 316 317 resp := Snapshot{ 318 CreatedAt: testTime, 319 Description: updateReq.Description, 320 ID: testId, 321 Name: updateReq.Name, 322 Size: 1, 323 Status: testStatus, 324 VolumeID: testId, 325 } 326 327 respBody, err := json.Marshal(&UpdateSnapshotResults{Snapshot: resp}) 328 c.Assert(err, gc.IsNil) 329 330 w.(*responseWriter).Response.StatusCode = 200 331 w.(*responseWriter).Body = ioutil.NopCloser(bytes.NewReader(respBody)) 332 }) 333 334 resp, err := s.client.UpdateSnapshot(testId, updateReq) 335 c.Assert(numCalls, gc.Equals, 1) 336 c.Assert(err, gc.IsNil) 337 338 c.Check(resp.Snapshot.CreatedAt, gc.Equals, testTime) 339 c.Check(resp.Snapshot.Description, gc.Equals, updateReq.Description) 340 c.Check(resp.Snapshot.ID, gc.Equals, testId) 341 c.Check(resp.Snapshot.Name, gc.Equals, updateReq.Name) 342 c.Check(resp.Snapshot.Size, gc.Equals, 1) 343 c.Check(resp.Snapshot.Status, gc.Equals, testStatus) 344 c.Check(resp.Snapshot.VolumeID, gc.Equals, testId) 345 } 346 347 func (s *CinderTestSuite) TestUpdateSnapshotMetadata(c *gc.C) { 348 349 numCalls := 0 350 s.HandleFunc("/v2/"+testId+"/snapshots/"+testId+"/metadata", func(w http.ResponseWriter, req *http.Request) { 351 numCalls++ 352 353 c.Check(req.Header["X-Auth-Token"], gc.DeepEquals, []string{testToken}) 354 355 reqBody, err := ioutil.ReadAll(req.Body) 356 c.Assert(err, gc.IsNil) 357 358 var receivedReq UpdateSnapshotMetadataParams 359 err = json.Unmarshal(reqBody, &receivedReq) 360 c.Assert(err, gc.IsNil) 361 362 c.Check(receivedReq.Metadata.Key, gc.DeepEquals, "test-key") 363 364 resp := struct { 365 Key string `json:"key"` 366 }{ 367 Key: receivedReq.Metadata.Key, 368 } 369 370 respBody, err := json.Marshal(&UpdateSnapshotMetadataResults{Metadata: resp}) 371 c.Assert(err, gc.IsNil) 372 373 w.(*responseWriter).Response.StatusCode = 200 374 w.(*responseWriter).Body = ioutil.NopCloser(bytes.NewReader(respBody)) 375 }) 376 377 resp, err := s.client.UpdateSnapshotMetadata(testId, "test-key") 378 c.Assert(numCalls, gc.Equals, 1) 379 c.Assert(err, gc.IsNil) 380 381 c.Check(resp.Metadata.Key, gc.Equals, "test-key") 382 } 383 384 func (s *CinderTestSuite) TestCreateVolume(c *gc.C) { 385 req := CreateVolumeVolumeParams{ 386 Description: testDescr, 387 Size: 1, 388 Name: testName, 389 } 390 391 numCalls := 0 392 s.HandleFunc("/v2/"+testId+"/volumes", func(w http.ResponseWriter, req *http.Request) { 393 numCalls++ 394 395 reqBody, err := ioutil.ReadAll(req.Body) 396 c.Assert(err, gc.IsNil) 397 398 var receivedReq CreateVolumeParams 399 err = json.Unmarshal(reqBody, &receivedReq) 400 c.Assert(err, gc.IsNil) 401 402 resp := Volume{ 403 AvailabilityZone: receivedReq.Volume.AvailabilityZone, 404 Bootable: fmt.Sprintf("%v", receivedReq.Volume.Bootable), 405 CreatedAt: "test-time", 406 Description: receivedReq.Volume.Description, 407 Name: receivedReq.Volume.Name, 408 Size: receivedReq.Volume.Size, 409 SnapshotID: testId, 410 SourceVolid: testId, 411 Status: testStatus, 412 VolumeType: "test-volume-type", 413 } 414 415 respBody, err := json.Marshal(&CreateVolumeResults{Volume: resp}) 416 c.Assert(err, gc.IsNil) 417 418 w.(*responseWriter).Response.StatusCode = 202 419 w.(*responseWriter).Body = ioutil.NopCloser(bytes.NewReader(respBody)) 420 c.Assert(w.(*responseWriter).Body, gc.NotNil) 421 }) 422 423 resp, err := s.client.CreateVolume(req) 424 c.Assert(numCalls, gc.Equals, 1) 425 c.Assert(err, gc.IsNil) 426 427 c.Check(resp.Volume.Name, gc.Equals, req.Name) 428 c.Check(resp.Volume.AvailabilityZone, gc.Equals, req.AvailabilityZone) 429 c.Check(resp.Volume.Bootable, gc.Equals, fmt.Sprintf("%v", req.Bootable)) 430 c.Check(resp.Volume.Description, gc.Equals, req.Description) 431 c.Check(resp.Volume.Size, gc.Equals, req.Size) 432 c.Check(resp.Volume.SnapshotID, gc.Equals, testId) 433 c.Check(resp.Volume.SourceVolid, gc.Equals, testId) 434 c.Check(resp.Volume.Status, gc.Equals, testStatus) 435 c.Check(resp.Volume.VolumeType, gc.Equals, "test-volume-type") 436 } 437 438 func (s *CinderTestSuite) TestDeleteVolume(c *gc.C) { 439 440 numCalls := 0 441 s.HandleFunc("/v2/"+testId+"/volumes/"+testId, func(w http.ResponseWriter, req *http.Request) { 442 numCalls++ 443 444 w.(*responseWriter).Response.StatusCode = 202 445 w.(*responseWriter).Body = ioutil.NopCloser(bytes.NewBuffer([]byte{})) 446 }) 447 448 err := s.client.DeleteVolume(testId) 449 c.Assert(numCalls, gc.Equals, 1) 450 c.Assert(err, gc.IsNil) 451 } 452 453 func (s *CinderTestSuite) TestUpdateVolume(c *gc.C) { 454 455 updateReq := UpdateVolumeVolumeParams{testName, testDescr} 456 457 numCalls := 0 458 s.HandleFunc("/v2/"+testId+"/volumes/"+testId, func(w http.ResponseWriter, req *http.Request) { 459 numCalls++ 460 461 reqBody, err := ioutil.ReadAll(req.Body) 462 c.Assert(err, gc.IsNil) 463 464 var receivedReq UpdateVolumeParams 465 err = json.Unmarshal(reqBody, &receivedReq) 466 c.Assert(err, gc.IsNil) 467 468 resp := Volume{ 469 AvailabilityZone: "test-avail-zone", 470 Bootable: "false", 471 CreatedAt: "test-time", 472 Description: receivedReq.Volume.Description, 473 Name: receivedReq.Volume.Name, 474 Size: 1, 475 SnapshotID: testId, 476 SourceVolid: testId, 477 Status: testStatus, 478 VolumeType: "test-volume-type", 479 } 480 481 respBody, err := json.Marshal(&CreateVolumeResults{Volume: resp}) 482 c.Assert(err, gc.IsNil) 483 484 w.(*responseWriter).Response.StatusCode = 200 485 w.(*responseWriter).Body = ioutil.NopCloser(bytes.NewReader(respBody)) 486 c.Assert(w.(*responseWriter).Body, gc.NotNil) 487 }) 488 489 resp, err := s.client.UpdateVolume(testId, updateReq) 490 c.Assert(numCalls, gc.Equals, 1) 491 c.Assert(err, gc.IsNil) 492 493 c.Check(resp.Volume.Name, gc.Equals, updateReq.Name) 494 c.Check(resp.Volume.AvailabilityZone, gc.Equals, "test-avail-zone") 495 c.Check(resp.Volume.Description, gc.Equals, updateReq.Description) 496 c.Check(resp.Volume.Size, gc.Equals, 1) 497 c.Check(resp.Volume.SnapshotID, gc.Equals, testId) 498 c.Check(resp.Volume.SourceVolid, gc.Equals, testId) 499 c.Check(resp.Volume.Status, gc.Equals, testStatus) 500 c.Check(resp.Volume.VolumeType, gc.Equals, "test-volume-type") 501 } 502 503 func (s *CinderTestSuite) TestUpdateVolumeType(c *gc.C) { 504 505 numCalls := 0 506 s.HandleFunc("/v2/"+testId+"/types/"+testId, func(w http.ResponseWriter, req *http.Request) { 507 numCalls++ 508 509 resp := struct { 510 ExtraSpecs struct { 511 Capabilities string `json:"capabilities"` 512 } `json:"extra_specs"` 513 ID string `json:"id"` 514 Name string `json:"name"` 515 }{ 516 ID: testId, 517 Name: testName, 518 } 519 520 respBody, err := json.Marshal(&UpdateVolumeTypeResults{VolumeType: resp}) 521 c.Assert(err, gc.IsNil) 522 523 w.(*responseWriter).Response.StatusCode = 200 524 w.(*responseWriter).Body = ioutil.NopCloser(bytes.NewBuffer(respBody)) 525 }) 526 527 resp, err := s.client.UpdateVolumeType(testId, "test-volume-type") 528 c.Assert(numCalls, gc.Equals, 1) 529 c.Assert(err, gc.IsNil) 530 531 c.Check(resp.VolumeType.Name, gc.Equals, testName) 532 c.Check(resp.VolumeType.ID, gc.Equals, testId) 533 } 534 535 func (s *CinderTestSuite) TestUpdateVolumeTypeExtraSpecs(c *gc.C) { 536 537 const ( 538 testType = "test-type" 539 testSpecs = "test-xtra-specs" 540 ) 541 542 numCalls := 0 543 s.HandleFunc("/v2/"+testId+"/types/"+testId, func(w http.ResponseWriter, req *http.Request) { 544 numCalls++ 545 546 reqBody, err := ioutil.ReadAll(req.Body) 547 c.Assert(err, gc.IsNil) 548 549 var receivedReq UpdateVolumeTypeExtraSpecsParams 550 err = json.Unmarshal(reqBody, &receivedReq) 551 c.Assert(err, gc.IsNil) 552 c.Check(receivedReq.ExtraSpecs, gc.Equals, testSpecs) 553 c.Check(receivedReq.VolumeType, gc.Equals, testType) 554 555 resp := struct { 556 ExtraSpecs struct { 557 Capabilities string `json:"capabilities"` 558 } `json:"extra_specs"` 559 ID string `json:"id"` 560 Name string `json:"name"` 561 }{ 562 ID: testId, 563 Name: testName, 564 ExtraSpecs: struct { 565 Capabilities string `json:"capabilities"` 566 }{ 567 Capabilities: testSpecs, 568 }, 569 } 570 571 respBody, err := json.Marshal(&UpdateVolumeTypeResults{VolumeType: resp}) 572 c.Assert(err, gc.IsNil) 573 574 w.(*responseWriter).Response.StatusCode = 200 575 w.(*responseWriter).Body = ioutil.NopCloser(bytes.NewBuffer(respBody)) 576 }) 577 578 resp, err := s.client.UpdateVolumeTypeExtraSpecs(testId, testType, testSpecs) 579 c.Assert(numCalls, gc.Equals, 1) 580 c.Assert(err, gc.IsNil) 581 582 c.Check(resp.VolumeType.ExtraSpecs.Capabilities, gc.Equals, testSpecs) 583 c.Check(resp.VolumeType.ID, gc.Equals, testId) 584 c.Check(resp.VolumeType.Name, gc.Equals, testName) 585 } 586 587 func (s *CinderTestSuite) TestGetVolumesDetail(c *gc.C) { 588 589 numCalls := 0 590 s.HandleFunc("/v2/"+testId+"/volumes/", func(w http.ResponseWriter, req *http.Request) { 591 numCalls++ 592 593 resp := []Volume{{ 594 AvailabilityZone: "test-availability-zone", 595 CreatedAt: testTime, 596 Description: testDescr, 597 ID: testId, 598 Name: testName, 599 Os_Vol_Host_Attr_Host: "test-host", 600 Os_Vol_Tenant_Attr_TenantID: testId, 601 Size: 1, 602 SnapshotID: testId, 603 SourceVolid: testId, 604 Status: testStatus, 605 VolumeType: "test-volume-type", 606 }} 607 608 respBody, err := json.Marshal(&GetVolumesDetailResults{Volumes: resp}) 609 c.Assert(err, gc.IsNil) 610 611 w.(*responseWriter).Response.StatusCode = 200 612 w.(*responseWriter).Body = ioutil.NopCloser(bytes.NewBuffer(respBody)) 613 }) 614 615 resp, err := s.client.GetVolumesDetail() 616 c.Assert(numCalls, gc.Equals, 1) 617 c.Assert(err, gc.IsNil) 618 c.Assert(resp.Volumes, gc.HasLen, 1) 619 620 volume := resp.Volumes[0] 621 622 c.Check(volume.AvailabilityZone, gc.Equals, "test-availability-zone") 623 c.Check(volume.CreatedAt, gc.Equals, testTime) 624 c.Check(volume.Description, gc.Equals, testDescr) 625 c.Check(volume.ID, gc.Equals, testId) 626 c.Check(volume.Name, gc.Equals, testName) 627 c.Check(volume.Os_Vol_Host_Attr_Host, gc.Equals, "test-host") 628 c.Check(volume.Os_Vol_Tenant_Attr_TenantID, gc.Equals, testId) 629 c.Check(volume.Size, gc.Equals, 1) 630 c.Check(volume.SnapshotID, gc.Equals, testId) 631 c.Check(volume.SourceVolid, gc.Equals, testId) 632 c.Check(volume.Status, gc.Equals, testStatus) 633 c.Check(volume.VolumeType, gc.Equals, "test-volume-type") 634 } 635 636 func (s *CinderTestSuite) TestGetVolumesSimple(c *gc.C) { 637 638 numCalls := 0 639 s.HandleFunc("/v2/"+testId+"/volumes", func(w http.ResponseWriter, req *http.Request) { 640 numCalls++ 641 642 resp := []Volume{{ 643 ID: testId, 644 Name: testName, 645 }} 646 647 respBody, err := json.Marshal(&GetVolumesSimpleResults{Volumes: resp}) 648 c.Assert(err, gc.IsNil) 649 650 w.(*responseWriter).Response.StatusCode = 200 651 w.(*responseWriter).Body = ioutil.NopCloser(bytes.NewBuffer(respBody)) 652 }) 653 654 resp, err := s.client.GetVolumesSimple() 655 c.Assert(numCalls, gc.Equals, 1) 656 c.Assert(err, gc.IsNil) 657 c.Assert(resp.Volumes, gc.HasLen, 1) 658 659 volume := resp.Volumes[0] 660 661 c.Check(volume.ID, gc.Equals, testId) 662 c.Check(volume.Name, gc.Equals, testName) 663 } 664 665 func (s *CinderTestSuite) TestCreateVolumeType(c *gc.C) { 666 origReq := CreateVolumeTypeVolumeTypeParams{ 667 Name: "test-volume-type", 668 ExtraSpecs: CreateVolumeTypeVolumeTypeExtraSpecsParams{ 669 Capabilities: "gpu", 670 }, 671 } 672 673 numCalls := 0 674 s.HandleFunc("/v2/"+testId+"/types", func(w http.ResponseWriter, req *http.Request) { 675 numCalls++ 676 677 reqBody, err := ioutil.ReadAll(req.Body) 678 c.Assert(err, gc.IsNil) 679 680 var receivedReq CreateVolumeTypeParams 681 err = json.Unmarshal(reqBody, &receivedReq) 682 c.Assert(err, gc.IsNil) 683 684 c.Check(receivedReq.VolumeType, gc.DeepEquals, origReq) 685 686 resp := struct { 687 ExtraSpecs struct { 688 Capabilities string `json:"capabilities"` 689 } `json:"extra_specs"` 690 ID string `json:"id"` 691 Name string `json:"name"` 692 }{ 693 ID: "test-id", 694 ExtraSpecs: struct { 695 Capabilities string `json:"capabilities"` 696 }{ 697 Capabilities: receivedReq.VolumeType.ExtraSpecs.Capabilities, 698 }, 699 Name: receivedReq.VolumeType.Name, 700 } 701 702 respBody, err := json.Marshal(&CreateVolumeTypeResults{VolumeType: resp}) 703 c.Assert(err, gc.IsNil) 704 705 w.(*responseWriter).StatusCode = 200 706 w.(*responseWriter).Body = ioutil.NopCloser(bytes.NewBuffer(respBody)) 707 }) 708 709 resp, err := s.client.CreateVolumeType(origReq) 710 c.Assert(err, gc.IsNil) 711 c.Assert(resp.VolumeType.ID, gc.Not(gc.HasLen), 0) 712 713 c.Check(resp.VolumeType.ExtraSpecs.Capabilities, gc.Equals, origReq.ExtraSpecs.Capabilities) 714 c.Check(resp.VolumeType.Name, gc.Equals, origReq.Name) 715 } 716 717 func (s *CinderTestSuite) TestDeleteVolumeType(c *gc.C) { 718 719 numCalls := 0 720 s.HandleFunc("/v2/"+testId+"/types/", func(w http.ResponseWriter, req *http.Request) { 721 numCalls++ 722 723 w.(*responseWriter).StatusCode = 202 724 w.(*responseWriter).Body = ioutil.NopCloser(bytes.NewBuffer([]byte{})) 725 }) 726 727 err := s.client.DeleteVolumeType(testId) 728 c.Assert(numCalls, gc.Equals, 1) 729 c.Assert(err, gc.IsNil) 730 } 731 732 func (s *CinderTestSuite) TestGetVolumeType(c *gc.C) { 733 734 numCalls := 0 735 s.HandleFunc("/v2/"+testId+"/types/"+testId, func(w http.ResponseWriter, req *http.Request) { 736 numCalls++ 737 738 resp := struct { 739 ExtraSpecs struct { 740 Capabilities string `json:"capabilities"` 741 } `json:"extra_specs"` 742 ID string `json:"id"` 743 Name string `json:"name"` 744 }{ 745 ID: testId, 746 ExtraSpecs: struct { 747 Capabilities string `json:"capabilities"` 748 }{ 749 Capabilities: "test-capability", 750 }, 751 Name: testName, 752 } 753 754 respBody, err := json.Marshal(&GetVolumeTypeResults{VolumeType: resp}) 755 c.Assert(err, gc.IsNil) 756 757 w.(*responseWriter).StatusCode = 200 758 w.(*responseWriter).Body = ioutil.NopCloser(bytes.NewBuffer(respBody)) 759 }) 760 761 resp, err := s.client.GetVolumeType(testId) 762 c.Assert(numCalls, gc.Equals, 1) 763 c.Assert(err, gc.IsNil) 764 c.Assert(resp.VolumeType.ID, gc.Not(gc.HasLen), 0) 765 766 c.Check(resp.VolumeType.ExtraSpecs.Capabilities, gc.Equals, "test-capability") 767 c.Check(resp.VolumeType.Name, gc.Equals, testName) 768 } 769 770 func (s *CinderTestSuite) TestGetVolumeTypes(c *gc.C) { 771 772 numCalls := 0 773 s.HandleFunc("/v2/"+testId+"/types", func(w http.ResponseWriter, req *http.Request) { 774 numCalls++ 775 776 resp := []VolumeType{{ 777 ID: testId, 778 ExtraSpecs: struct { 779 Capabilities string `json:"capabilities"` 780 }{ 781 Capabilities: "test-capability", 782 }, 783 Name: testName, 784 }} 785 786 respBody, err := json.Marshal(&GetVolumeTypesResults{VolumeTypes: resp}) 787 c.Assert(err, gc.IsNil) 788 789 w.(*responseWriter).StatusCode = 200 790 w.(*responseWriter).Body = ioutil.NopCloser(bytes.NewBuffer(respBody)) 791 }) 792 793 resp, err := s.client.GetVolumeTypes() 794 c.Assert(numCalls, gc.Equals, 1) 795 c.Assert(err, gc.IsNil) 796 c.Assert(resp.VolumeTypes, gc.HasLen, 1) 797 798 volumeType := resp.VolumeTypes[0] 799 800 c.Check(volumeType.ExtraSpecs.Capabilities, gc.Equals, "test-capability") 801 c.Check(volumeType.Name, gc.Equals, testName) 802 c.Check(volumeType.ID, gc.Equals, testId) 803 } 804 805 func (s *CinderTestSuite) TestGetAvailabilityZones(c *gc.C) { 806 807 numCalls := 0 808 s.HandleFunc("/v2/"+testId+"/os-availability-zone", func(w http.ResponseWriter, req *http.Request) { 809 numCalls++ 810 811 resp := []AvailabilityZone{{ 812 Name: "zone-1", 813 State: AvailabilityZoneState{ 814 Available: true, 815 }, 816 }} 817 818 respBody, err := json.Marshal(&GetAvailabilityZonesResults{AvailabilityZoneInfo: resp}) 819 c.Assert(err, gc.IsNil) 820 821 w.(*responseWriter).StatusCode = 200 822 w.(*responseWriter).Body = ioutil.NopCloser(bytes.NewBuffer(respBody)) 823 }) 824 825 zones, err := s.client.ListVolumeAvailabilityZones() 826 c.Assert(numCalls, gc.Equals, 1) 827 c.Assert(err, gc.IsNil) 828 c.Assert(zones, gc.HasLen, 1) 829 830 zone := zones[0] 831 832 c.Check(zone.Name, gc.Equals, "zone-1") 833 c.Check(zone.State.Available, gc.Equals, true) 834 } 835 836 func (s *CinderTestSuite) localDo(req *http.Request) (*http.Response, error) { 837 handler, matchedPattern := s.Handler(req) 838 if matchedPattern == "" { 839 return nil, fmt.Errorf("no test handler registered for %s", req.URL.Path) 840 } 841 842 var response http.Response 843 handler.ServeHTTP(&responseWriter{&response}, req) 844 845 return &response, nil 846 } 847 848 type responseWriter struct { 849 *http.Response 850 } 851 852 func (w *responseWriter) Header() http.Header { 853 return w.Response.Header 854 } 855 856 func (w *responseWriter) Write(data []byte) (int, error) { 857 return len(data), w.Response.Write(bytes.NewBuffer(data)) 858 } 859 860 func (w *responseWriter) WriteHeader(statusCode int) { 861 w.Response.StatusCode = statusCode 862 }