github.com/minio/console@v1.3.0/integration/user_api_bucket_test.go (about) 1 // This file is part of MinIO Console Server 2 // Copyright (c) 2021 MinIO, Inc. 3 // 4 // This program is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Affero General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // This program is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Affero General Public License for more details. 13 // 14 // You should have received a copy of the GNU Affero General Public License 15 // along with this program. If not, see <http://www.gnu.org/licenses/>. 16 17 // These tests are for UserAPI Tag based on swagger-console.yml 18 19 package integration 20 21 import ( 22 "bytes" 23 "context" 24 "encoding/base64" 25 "encoding/json" 26 "errors" 27 "fmt" 28 "io" 29 "log" 30 "net/http" 31 "os" 32 "strconv" 33 "strings" 34 "testing" 35 "time" 36 37 "github.com/minio/minio-go/v7" 38 39 "github.com/minio/console/models" 40 "github.com/minio/minio-go/v7/pkg/credentials" 41 "github.com/stretchr/testify/assert" 42 ) 43 44 type AddBucketOps struct { 45 Name string 46 Locking bool 47 Versioning map[string]interface{} 48 Quota map[string]interface{} 49 Retention map[string]interface{} 50 Endpoint *string 51 UseToken *string 52 } 53 54 func AddBucket(name string, locking bool, versioning, quota, retention map[string]interface{}) (*http.Response, error) { 55 return AddBucketWithOpts(&AddBucketOps{ 56 Name: name, 57 Locking: locking, 58 Versioning: versioning, 59 Quota: quota, 60 Retention: retention, 61 Endpoint: nil, 62 }) 63 } 64 65 func AddBucketWithOpts(opts *AddBucketOps) (*http.Response, error) { 66 /* 67 This is an atomic function that we can re-use to create a bucket on any 68 desired test. 69 */ 70 // Needed Parameters for API Call 71 requestDataAdd := map[string]interface{}{ 72 "name": opts.Name, 73 "locking": opts.Locking, 74 "versioning": opts.Versioning, 75 "quota": opts.Quota, 76 "retention": opts.Retention, 77 } 78 79 endpoint := "http://localhost:9090/api/v1/buckets" 80 if opts.Endpoint != nil { 81 endpoint = fmt.Sprintf("%s/api/v1/buckets", *opts.Endpoint) 82 } 83 84 // Creating the Call by adding the URL and Headers 85 requestDataJSON, _ := json.Marshal(requestDataAdd) 86 requestDataBody := bytes.NewReader(requestDataJSON) 87 request, err := http.NewRequest("POST", endpoint, requestDataBody) 88 if err != nil { 89 log.Println(err) 90 } 91 if opts.UseToken != nil { 92 request.Header.Add("Cookie", fmt.Sprintf("token=%s", *opts.UseToken)) 93 } else { 94 request.Header.Add("Cookie", fmt.Sprintf("token=%s", token)) 95 } 96 request.Header.Add("Content-Type", "application/json") 97 98 // Performing the call 99 client := &http.Client{ 100 Timeout: 2 * time.Second, 101 } 102 response, err := client.Do(request) 103 return response, err 104 } 105 106 func getTokenForEndpoint(endpoint string) string { 107 var loginToken string 108 client := &http.Client{ 109 Timeout: 2 * time.Second, 110 } 111 // get login credentials 112 113 requestData := map[string]string{ 114 "accessKey": "minioadmin", 115 "secretKey": "minioadmin", 116 } 117 118 requestDataJSON, _ := json.Marshal(requestData) 119 120 requestDataBody := bytes.NewReader(requestDataJSON) 121 122 request, err := http.NewRequest("POST", fmt.Sprintf("%s/api/v1/login", endpoint), requestDataBody) 123 if err != nil { 124 log.Println(err) 125 return "" 126 } 127 128 request.Header.Add("Content-Type", "application/json") 129 130 response, err := client.Do(request) 131 if err != nil { 132 log.Println(err) 133 return "" 134 } 135 136 if response != nil { 137 for _, cookie := range response.Cookies() { 138 if cookie.Name == "token" { 139 loginToken = cookie.Value 140 break 141 } 142 } 143 } 144 return loginToken 145 } 146 147 func setupBucket(name string, locking bool, versioning, quota, retention map[string]interface{}, assert *assert.Assertions, expected int) bool { 148 return setupBucketForEndpoint(name, locking, versioning, quota, retention, assert, expected, nil, nil) 149 } 150 151 func setupBucketForEndpoint(name string, locking bool, versioning, quota, retention map[string]interface{}, assert *assert.Assertions, expected int, endpoint, endpointToken *string) bool { 152 /* 153 The intention of this function is to return either true or false to 154 reduce the code by performing the verification in one place only. 155 */ 156 // Verify if there is an error and return either true or false 157 response, err := AddBucketWithOpts(&AddBucketOps{ 158 Name: name, 159 Locking: locking, 160 Versioning: versioning, 161 Quota: quota, 162 Retention: retention, 163 Endpoint: endpoint, 164 UseToken: endpointToken, 165 }) 166 if err != nil { 167 assert.Fail("Error adding the bucket") 168 return false 169 } 170 if response != nil { 171 if response.StatusCode >= 200 && response.StatusCode <= 299 { 172 fmt.Println("setupBucketForEndpoint(): HTTP Status is in the 2xx range") 173 return true 174 } 175 if response.StatusCode != expected { 176 assert.Fail(inspectHTTPResponse(response)) 177 return false 178 } 179 } 180 return true 181 } 182 183 func ListBuckets() (*http.Response, error) { 184 /* 185 Helper function to list buckets 186 HTTP Verb: GET 187 {{baseUrl}}/buckets?sort_by=proident velit&offset=-5480083&limit=-5480083 188 */ 189 request, err := http.NewRequest( 190 "GET", "http://localhost:9090/api/v1/buckets", nil) 191 if err != nil { 192 log.Println(err) 193 } 194 request.Header.Add("Cookie", fmt.Sprintf("token=%s", token)) 195 request.Header.Add("Content-Type", "application/json") 196 client := &http.Client{ 197 Timeout: 2 * time.Second, 198 } 199 response, err := client.Do(request) 200 return response, err 201 } 202 203 func DeleteBucket(name string) (*http.Response, error) { 204 /* 205 Helper function to delete bucket. 206 DELETE: {{baseUrl}}/buckets/:name 207 */ 208 request, err := http.NewRequest( 209 "DELETE", "http://localhost:9090/api/v1/buckets/"+name, nil) 210 if err != nil { 211 log.Println(err) 212 } 213 request.Header.Add("Cookie", fmt.Sprintf("token=%s", token)) 214 request.Header.Add("Content-Type", "application/json") 215 client := &http.Client{ 216 Timeout: 2 * time.Second, 217 } 218 response, err := client.Do(request) 219 return response, err 220 } 221 222 func BucketInfo(name string) (*http.Response, error) { 223 /* 224 Helper function to test Bucket Info End Point 225 GET: {{baseUrl}}/buckets/:name 226 */ 227 bucketInformationRequest, bucketInformationError := http.NewRequest( 228 "GET", "http://localhost:9090/api/v1/buckets/"+name, nil) 229 if bucketInformationError != nil { 230 log.Println(bucketInformationError) 231 } 232 bucketInformationRequest.Header.Add("Cookie", 233 fmt.Sprintf("token=%s", token)) 234 bucketInformationRequest.Header.Add("Content-Type", "application/json") 235 client := &http.Client{ 236 Timeout: 2 * time.Second, 237 } 238 response, err := client.Do(bucketInformationRequest) 239 return response, err 240 } 241 242 func SetBucketRetention(bucketName, mode, unit string, validity int) (*http.Response, error) { 243 /* 244 Helper function to set bucket's retention 245 PUT: {{baseUrl}}/buckets/:bucket_name/retention 246 { 247 "mode":"compliance", 248 "unit":"years", 249 "validity":2 250 } 251 */ 252 requestDataAdd := map[string]interface{}{ 253 "mode": mode, 254 "unit": unit, 255 "validity": validity, 256 } 257 requestDataJSON, _ := json.Marshal(requestDataAdd) 258 requestDataBody := bytes.NewReader(requestDataJSON) 259 request, err := http.NewRequest("PUT", 260 "http://localhost:9090/api/v1/buckets/"+bucketName+"/retention", 261 requestDataBody) 262 if err != nil { 263 log.Println(err) 264 } 265 request.Header.Add("Cookie", fmt.Sprintf("token=%s", token)) 266 request.Header.Add("Content-Type", "application/json") 267 client := &http.Client{ 268 Timeout: 2 * time.Second, 269 } 270 response, err := client.Do(request) 271 return response, err 272 } 273 274 func GetBucketRetention(bucketName string) (*http.Response, error) { 275 /* 276 Helper function to get the bucket's retention 277 */ 278 request, err := http.NewRequest("GET", 279 "http://localhost:9090/api/v1/buckets/"+bucketName+"/retention", 280 nil) 281 if err != nil { 282 log.Println(err) 283 } 284 request.Header.Add("Cookie", fmt.Sprintf("token=%s", token)) 285 request.Header.Add("Content-Type", "application/json") 286 client := &http.Client{ 287 Timeout: 2 * time.Second, 288 } 289 response, err := client.Do(request) 290 return response, err 291 } 292 293 func PutObjectTags(bucketName, prefix string, tags map[string]string, versionID string) (*http.Response, error) { 294 /* 295 Helper function to put object's tags. 296 PUT: /buckets/{bucket_name}/objects/tags?prefix=prefix 297 { 298 "tags": {} 299 } 300 */ 301 requestDataAdd := map[string]interface{}{ 302 "tags": tags, 303 } 304 requestDataJSON, _ := json.Marshal(requestDataAdd) 305 requestDataBody := bytes.NewReader(requestDataJSON) 306 request, err := http.NewRequest( 307 "PUT", 308 "http://localhost:9090/api/v1/buckets/"+ 309 bucketName+"/objects/tags?prefix="+prefix+"&version_id="+versionID, 310 requestDataBody, 311 ) 312 if err != nil { 313 log.Println(err) 314 } 315 request.Header.Add("Cookie", fmt.Sprintf("token=%s", token)) 316 request.Header.Add("Content-Type", "application/json") 317 client := &http.Client{ 318 Timeout: 2 * time.Second, 319 } 320 response, err := client.Do(request) 321 return response, err 322 } 323 324 func DeleteMultipleObjects(bucketName string, files []map[string]interface{}) (*http.Response, error) { 325 /* 326 Helper function to delete multiple objects in a container. 327 POST: /buckets/{bucket_name}/delete-objects 328 Example of the data being sent: 329 [ 330 { 331 "path": "testdeletemultipleobjs1.txt", 332 "versionID": "", 333 "recursive": false 334 }, 335 { 336 "path": "testdeletemultipleobjs2.txt", 337 "versionID": "", 338 "recursive": false 339 }, 340 ] 341 */ 342 requestDataJSON, _ := json.Marshal(files) 343 requestDataBody := bytes.NewReader(requestDataJSON) 344 request, err := http.NewRequest( 345 "POST", 346 "http://localhost:9090/api/v1/buckets/"+bucketName+"/delete-objects", 347 requestDataBody, 348 ) 349 if err != nil { 350 log.Println(err) 351 } 352 request.Header.Add("Cookie", fmt.Sprintf("token=%s", token)) 353 request.Header.Add("Content-Type", "application/json") 354 client := &http.Client{ 355 Timeout: 2 * time.Second, 356 } 357 response, err := client.Do(request) 358 return response, err 359 } 360 361 func DownloadObject(bucketName, path string) (*http.Response, error) { 362 /* 363 Helper function to download an object from a bucket. 364 GET: {{baseUrl}}/buckets/bucketName/objects/download?prefix=file 365 */ 366 request, err := http.NewRequest( 367 "GET", 368 "http://localhost:9090/api/v1/buckets/"+bucketName+"/objects/download?prefix="+ 369 path, 370 nil, 371 ) 372 if err != nil { 373 log.Println(err) 374 } 375 request.Header.Add("Cookie", fmt.Sprintf("token=%s", token)) 376 request.Header.Add("Content-Type", "application/json") 377 client := &http.Client{ 378 Timeout: 2 * time.Second, 379 } 380 response, err := client.Do(request) 381 return response, err 382 } 383 384 func UploadAnObject(bucketName, fileName string) (*http.Response, error) { 385 /* 386 Helper function to upload a file to a bucket for testing. 387 POST {{baseUrl}}/buckets/:bucket_name/objects/upload 388 */ 389 boundary := "WebKitFormBoundaryWtayBM7t9EUQb8q3" 390 boundaryStart := "------" + boundary + "\r\n" 391 contentDispositionOne := "Content-Disposition: form-data; name=\"2\"; " 392 contentDispositionTwo := "filename=\"" + fileName + "\"\r\n" 393 contentType := "Content-Type: text/plain\r\n\r\na\n\r\n" 394 boundaryEnd := "------" + boundary + "--\r\n" 395 file := boundaryStart + contentDispositionOne + contentDispositionTwo + 396 contentType + boundaryEnd 397 arrayOfBytes := []byte(file) 398 requestDataBody := bytes.NewReader(arrayOfBytes) 399 apiURL := "http://localhost:9090/api/v1/buckets/" + bucketName + "/objects/upload" + "?prefix=" + base64.StdEncoding.EncodeToString([]byte(fileName)) 400 request, err := http.NewRequest( 401 "POST", 402 apiURL, 403 requestDataBody, 404 ) 405 if err != nil { 406 log.Println(err) 407 } 408 request.Header.Add("Cookie", fmt.Sprintf("token=%s", token)) 409 request.Header.Add( 410 "Content-Type", 411 "multipart/form-data; boundary=----"+boundary, 412 ) 413 client := &http.Client{ 414 Timeout: 2 * time.Second, 415 } 416 response, err := client.Do(request) 417 return response, err 418 } 419 420 func DeleteObject(bucketName, path string, recursive, allVersions bool) (*http.Response, error) { 421 /* 422 Helper function to delete an object from a given bucket. 423 DELETE: 424 {{baseUrl}}/buckets/bucketName/objects?path=Y2VzYXJpby50eHQ=&recursive=false&all_versions=false 425 */ 426 prefixEncoded := base64.StdEncoding.EncodeToString([]byte(path)) 427 url := "http://localhost:9090/api/v1/buckets/" + bucketName + "/objects?prefix=" + 428 prefixEncoded + "&recursive=" + strconv.FormatBool(recursive) + "&all_versions=" + 429 strconv.FormatBool(allVersions) 430 request, err := http.NewRequest( 431 "DELETE", 432 url, 433 nil, 434 ) 435 if err != nil { 436 log.Println(err) 437 } 438 request.Header.Add("Cookie", fmt.Sprintf("token=%s", token)) 439 request.Header.Add("Content-Type", "application/json") 440 client := &http.Client{ 441 Timeout: 2 * time.Second, 442 } 443 response, err := client.Do(request) 444 return response, err 445 } 446 447 func ListObjects(bucketName, prefix, withVersions string) (*http.Response, error) { 448 /* 449 Helper function to list objects in a bucket. 450 GET: {{baseUrl}}/buckets/:bucket_name/objects 451 */ 452 request, err := http.NewRequest("GET", 453 "http://localhost:9090/api/v1/buckets/"+bucketName+"/objects?prefix="+prefix+"&with_versions="+withVersions, 454 nil) 455 if err != nil { 456 log.Println(err) 457 } 458 request.Header.Add("Cookie", fmt.Sprintf("token=%s", token)) 459 request.Header.Add("Content-Type", "application/json") 460 client := &http.Client{ 461 Timeout: 2 * time.Second, 462 } 463 response, err := client.Do(request) 464 return response, err 465 } 466 467 func SharesAnObjectOnAUrl(bucketName, prefix, versionID, expires string) (*http.Response, error) { 468 // Helper function to share an object on a url 469 request, err := http.NewRequest( 470 "GET", 471 "http://localhost:9090/api/v1/buckets/"+bucketName+"/objects/share?prefix="+prefix+"&version_id="+versionID+"&expires="+expires, 472 nil, 473 ) 474 if err != nil { 475 log.Println(err) 476 } 477 request.Header.Add("Cookie", fmt.Sprintf("token=%s", token)) 478 request.Header.Add("Content-Type", "application/json") 479 client := &http.Client{ 480 Timeout: 2 * time.Second, 481 } 482 response, err := client.Do(request) 483 return response, err 484 } 485 486 func PutObjectsRetentionStatus(bucketName, prefix, versionID, mode, expires string, governanceBypass bool) (*http.Response, error) { 487 requestDataAdd := map[string]interface{}{ 488 "mode": mode, 489 "expires": expires, 490 "governance_bypass": governanceBypass, 491 } 492 requestDataJSON, _ := json.Marshal(requestDataAdd) 493 requestDataBody := bytes.NewReader(requestDataJSON) 494 apiURL := "http://localhost:9090/api/v1/buckets/" + bucketName + "/objects/retention?prefix=" + prefix + "&version_id=" + versionID 495 496 request, err := http.NewRequest( 497 "PUT", 498 apiURL, 499 requestDataBody, 500 ) 501 if err != nil { 502 log.Println(err) 503 } 504 request.Header.Add("Cookie", fmt.Sprintf("token=%s", token)) 505 request.Header.Add("Content-Type", "application/json") 506 client := &http.Client{ 507 Timeout: 2 * time.Second, 508 } 509 response, err := client.Do(request) 510 return response, err 511 } 512 513 func GetsTheMetadataOfAnObject(bucketName, prefix string) (*http.Response, error) { 514 /* 515 Gets the metadata of an object 516 GET 517 {{baseUrl}}/buckets/:bucket_name/objects/metadata?prefix=proident velit 518 */ 519 request, err := http.NewRequest( 520 "GET", 521 "http://localhost:9090/api/v1/buckets/"+bucketName+"/objects/metadata?prefix="+prefix, 522 nil, 523 ) 524 if err != nil { 525 log.Println(err) 526 } 527 request.Header.Add("Cookie", fmt.Sprintf("token=%s", token)) 528 request.Header.Add("Content-Type", "application/json") 529 client := &http.Client{ 530 Timeout: 2 * time.Second, 531 } 532 response, err := client.Do(request) 533 return response, err 534 } 535 536 func PutBucketsTags(bucketName string, tags map[string]string) (*http.Response, error) { 537 /* 538 Helper function to put bucket's tags. 539 PUT: {{baseUrl}}/buckets/:bucket_name/tags 540 { 541 "tags": {} 542 } 543 */ 544 requestDataAdd := map[string]interface{}{ 545 "tags": tags, 546 } 547 requestDataJSON, _ := json.Marshal(requestDataAdd) 548 requestDataBody := bytes.NewReader(requestDataJSON) 549 request, err := http.NewRequest("PUT", 550 "http://localhost:9090/api/v1/buckets/"+bucketName+"/tags", 551 requestDataBody) 552 if err != nil { 553 log.Println(err) 554 } 555 request.Header.Add("Cookie", fmt.Sprintf("token=%s", token)) 556 request.Header.Add("Content-Type", "application/json") 557 client := &http.Client{ 558 Timeout: 2 * time.Second, 559 } 560 response, err := client.Do(request) 561 return response, err 562 } 563 564 func RestoreObjectToASelectedVersion(bucketName, prefix, versionID string) (*http.Response, error) { 565 request, err := http.NewRequest( 566 "PUT", 567 "http://localhost:9090/api/v1/buckets/"+bucketName+"/objects/restore?prefix="+prefix+"&version_id="+versionID, 568 nil, 569 ) 570 if err != nil { 571 log.Println(err) 572 } 573 request.Header.Add("Cookie", fmt.Sprintf("token=%s", token)) 574 request.Header.Add("Content-Type", "application/json") 575 client := &http.Client{ 576 Timeout: 2 * time.Second, 577 } 578 response, err := client.Do(request) 579 return response, err 580 } 581 582 func BucketSetPolicy(bucketName, access, definition string) (*http.Response, error) { 583 /* 584 Helper function to set policy on a bucket 585 Name: Bucket Set Policy 586 HTTP Verb: PUT 587 URL: {{baseUrl}}/buckets/:name/set-policy 588 Body: 589 { 590 "access": "PRIVATE", 591 "definition": "dolo" 592 } 593 */ 594 requestDataAdd := map[string]interface{}{ 595 "access": access, 596 "definition": definition, 597 } 598 requestDataJSON, _ := json.Marshal(requestDataAdd) 599 requestDataBody := bytes.NewReader(requestDataJSON) 600 request, err := http.NewRequest( 601 "PUT", 602 "http://localhost:9090/api/v1/buckets/"+bucketName+"/set-policy", 603 requestDataBody, 604 ) 605 if err != nil { 606 log.Println(err) 607 } 608 request.Header.Add("Cookie", fmt.Sprintf("token=%s", token)) 609 request.Header.Add("Content-Type", "application/json") 610 client := &http.Client{ 611 Timeout: 2 * time.Second, 612 } 613 response, err := client.Do(request) 614 return response, err 615 } 616 617 func DeleteObjectsRetentionStatus(bucketName, prefix, versionID string) (*http.Response, error) { 618 /* 619 Helper function to Delete Object Retention Status 620 DELETE: 621 {{baseUrl}}/buckets/:bucket_name/objects/retention?prefix=proident velit&version_id=proident velit 622 */ 623 url := "http://localhost:9090/api/v1/buckets/" + bucketName + "/objects/retention?prefix=" + 624 prefix + "&version_id=" + versionID 625 request, err := http.NewRequest( 626 "DELETE", 627 url, 628 nil, 629 ) 630 if err != nil { 631 log.Println(err) 632 } 633 request.Header.Add("Cookie", fmt.Sprintf("token=%s", token)) 634 request.Header.Add("Content-Type", "application/json") 635 client := &http.Client{ 636 Timeout: 2 * time.Second, 637 } 638 response, err := client.Do(request) 639 return response, err 640 } 641 642 func ListBucketEvents(bucketName string) (*http.Response, error) { 643 /* 644 Helper function to list bucket's events 645 Name: List Bucket Events 646 HTTP Verb: GET 647 URL: {{baseUrl}}/buckets/:bucket_name/events 648 */ 649 request, err := http.NewRequest( 650 "GET", 651 "http://localhost:9090/api/v1/buckets/"+bucketName+"/events", 652 nil, 653 ) 654 if err != nil { 655 log.Println(err) 656 } 657 request.Header.Add("Cookie", fmt.Sprintf("token=%s", token)) 658 request.Header.Add("Content-Type", "application/json") 659 client := &http.Client{ 660 Timeout: 2 * time.Second, 661 } 662 response, err := client.Do(request) 663 return response, err 664 } 665 666 func PutBucketQuota(bucketName string, enabled bool, quotaType string, amount int) (*http.Response, error) { 667 /* 668 Helper function to put bucket quota 669 Name: Bucket Quota 670 URL: {{baseUrl}}/buckets/:name/quota 671 HTTP Verb: PUT 672 Body: 673 { 674 "enabled": false, 675 "quota_type": "fifo", 676 "amount": 18462288 677 } 678 */ 679 requestDataAdd := map[string]interface{}{ 680 "enabled": enabled, 681 "quota_type": quotaType, 682 "amount": amount, 683 } 684 requestDataJSON, _ := json.Marshal(requestDataAdd) 685 requestDataBody := bytes.NewReader(requestDataJSON) 686 request, err := http.NewRequest( 687 "PUT", 688 "http://localhost:9090/api/v1/buckets/"+bucketName+"/quota", 689 requestDataBody, 690 ) 691 if err != nil { 692 log.Println(err) 693 } 694 request.Header.Add("Cookie", fmt.Sprintf("token=%s", token)) 695 request.Header.Add("Content-Type", "application/json") 696 client := &http.Client{ 697 Timeout: 2 * time.Second, 698 } 699 response, err := client.Do(request) 700 return response, err 701 } 702 703 func GetBucketQuota(bucketName string) (*http.Response, error) { 704 /* 705 Helper function to get bucket quota 706 Name: Get Bucket Quota 707 URL: {{baseUrl}}/buckets/:name/quota 708 HTTP Verb: GET 709 */ 710 request, err := http.NewRequest( 711 "GET", 712 "http://localhost:9090/api/v1/buckets/"+bucketName+"/quota", 713 nil, 714 ) 715 if err != nil { 716 log.Println(err) 717 } 718 request.Header.Add("Cookie", fmt.Sprintf("token=%s", token)) 719 request.Header.Add("Content-Type", "application/json") 720 client := &http.Client{ 721 Timeout: 2 * time.Second, 722 } 723 response, err := client.Do(request) 724 return response, err 725 } 726 727 func PutObjectsLegalholdStatus(bucketName, prefix, status, versionID string) (*http.Response, error) { 728 // Helper function to test "Put Object's legalhold status" end point 729 requestDataAdd := map[string]interface{}{ 730 "status": status, 731 } 732 requestDataJSON, _ := json.Marshal(requestDataAdd) 733 requestDataBody := bytes.NewReader(requestDataJSON) 734 apiURL := "http://localhost:9090/api/v1/buckets/" + bucketName + "/objects/legalhold?prefix=" + prefix + "&version_id=" + versionID 735 request, err := http.NewRequest( 736 "PUT", 737 apiURL, 738 requestDataBody, 739 ) 740 if err != nil { 741 log.Println(err) 742 } 743 request.Header.Add("Cookie", fmt.Sprintf("token=%s", token)) 744 request.Header.Add("Content-Type", "application/json") 745 client := &http.Client{ 746 Timeout: 2 * time.Second, 747 } 748 response, err := client.Do(request) 749 return response, err 750 } 751 752 func TestPutObjectsLegalholdStatus(t *testing.T) { 753 // Variables 754 assert := assert.New(t) 755 bucketName := "testputobjectslegalholdstatus" 756 objName := "testputobjectslegalholdstatus.txt" // // encoded base64 of testputobjectslegalholdstatus.txt = dGVzdHB1dG9iamVjdHNsZWdhbGhvbGRzdGF0dXMudHh0 757 objectNameEncoded := "dGVzdHB1dG9iamVjdHNsZWdhbGhvbGRzdGF0dXMudHh0" 758 status := "enabled" 759 760 // 1. Create bucket 761 if !setupBucket(bucketName, true, map[string]interface{}{"enabled": true}, nil, nil, assert, 200) { 762 return 763 } 764 765 // 2. Add object 766 uploadResponse, uploadError := UploadAnObject( 767 bucketName, 768 objName, 769 ) 770 assert.Nil(uploadError) 771 if uploadError != nil { 772 log.Println(uploadError) 773 return 774 } 775 addObjRsp := inspectHTTPResponse(uploadResponse) 776 if uploadResponse != nil { 777 assert.Equal( 778 200, 779 uploadResponse.StatusCode, 780 addObjRsp, 781 ) 782 } 783 784 // Get versionID 785 listResponse, _ := ListObjects(bucketName, "", "true") 786 bodyBytes, _ := io.ReadAll(listResponse.Body) 787 listObjs := models.ListObjectsResponse{} 788 err := json.Unmarshal(bodyBytes, &listObjs) 789 if err != nil { 790 log.Println(err) 791 assert.Nil(err) 792 } 793 validVersionID := listObjs.Objects[0].VersionID 794 795 type args struct { 796 versionID string 797 } 798 tests := []struct { 799 name string 800 expectedStatus int 801 args args 802 }{ 803 { 804 name: "Valid VersionID when putting object's legal hold status", 805 expectedStatus: 200, 806 args: args{ 807 versionID: validVersionID, 808 }, 809 }, 810 { 811 name: "Invalid VersionID when putting object's legal hold status", 812 expectedStatus: 500, 813 args: args{ 814 versionID: "*&^###Test1ThisMightBeInvalid555", 815 }, 816 }, 817 } 818 for _, tt := range tests { 819 t.Run(tt.name, func(_ *testing.T) { 820 // 3. Put Objects Legal Status 821 putResponse, putError := PutObjectsLegalholdStatus( 822 bucketName, 823 objectNameEncoded, 824 status, 825 tt.args.versionID, 826 ) 827 if putError != nil { 828 log.Println(putError) 829 assert.Fail("Error putting object's legal hold status") 830 } 831 if putResponse != nil { 832 assert.Equal( 833 tt.expectedStatus, 834 putResponse.StatusCode, 835 inspectHTTPResponse(putResponse), 836 ) 837 } 838 }) 839 } 840 } 841 842 func TestGetBucketQuota(t *testing.T) { 843 // Variables 844 assert := assert.New(t) 845 validBucket := "testgetbucketquota" 846 847 // 1. Create bucket 848 if !setupBucket(validBucket, true, map[string]interface{}{"enabled": true}, nil, nil, assert, 200) { 849 return 850 } 851 852 // 2. Put Bucket Quota 853 restResp, restErr := PutBucketQuota( 854 validBucket, 855 true, // enabled 856 "hard", // quotaType 857 1099511627776, // amount 858 ) 859 assert.Nil(restErr) 860 if restErr != nil { 861 log.Println(restErr) 862 return 863 } 864 finalResponse := inspectHTTPResponse(restResp) 865 if restResp != nil { 866 assert.Equal( 867 200, 868 restResp.StatusCode, 869 finalResponse, 870 ) 871 } 872 873 // 3. Get Bucket Quota 874 type args struct { 875 bucketName string 876 } 877 tests := []struct { 878 name string 879 expectedStatus int 880 args args 881 }{ 882 { 883 name: "Valid bucket when getting quota", 884 expectedStatus: 200, 885 args: args{ 886 bucketName: validBucket, 887 }, 888 }, 889 { 890 name: "Invalid bucket when getting quota", 891 expectedStatus: 500, 892 args: args{ 893 bucketName: "askdaklsjdkasjdklasjdklasjdklajsdklasjdklasjdlkas", 894 }, 895 }, 896 } 897 for _, tt := range tests { 898 t.Run(tt.name, func(_ *testing.T) { 899 restResp, restErr := GetBucketQuota( 900 tt.args.bucketName, 901 ) 902 assert.Nil(restErr) 903 if restErr != nil { 904 log.Println(restErr) 905 return 906 } 907 finalResponse := inspectHTTPResponse(restResp) 908 if restResp != nil { 909 assert.Equal( 910 tt.expectedStatus, 911 restResp.StatusCode, 912 finalResponse, 913 ) 914 } 915 }) 916 } 917 } 918 919 func TestPutBucketQuota(t *testing.T) { 920 // Variables 921 assert := assert.New(t) 922 validBucket := "testputbucketquota" 923 924 // 1. Create bucket 925 if !setupBucket(validBucket, true, map[string]interface{}{"enabled": true}, nil, nil, assert, 200) { 926 return 927 } 928 929 // 2. Put Bucket Quota 930 type args struct { 931 bucketName string 932 } 933 tests := []struct { 934 name string 935 expectedStatus int 936 args args 937 }{ 938 { 939 name: "Valid bucket when putting quota", 940 expectedStatus: 200, 941 args: args{ 942 bucketName: validBucket, 943 }, 944 }, 945 { 946 name: "Invalid bucket when putting quota", 947 expectedStatus: 500, 948 args: args{ 949 bucketName: "lksdjakldjklajdlkasjdklasjdkljaskdljaslkdjalksjdklasjdklajsdlkajs", 950 }, 951 }, 952 } 953 for _, tt := range tests { 954 t.Run(tt.name, func(_ *testing.T) { 955 restResp, restErr := PutBucketQuota( 956 tt.args.bucketName, 957 true, // enabled 958 "hard", // quotaType 959 1099511627776, // amount 960 ) 961 assert.Nil(restErr) 962 if restErr != nil { 963 log.Println(restErr) 964 return 965 } 966 finalResponse := inspectHTTPResponse(restResp) 967 if restResp != nil { 968 assert.Equal( 969 tt.expectedStatus, 970 restResp.StatusCode, 971 finalResponse, 972 ) 973 } 974 }) 975 } 976 } 977 978 func TestListBucketEvents(t *testing.T) { 979 // Variables 980 assert := assert.New(t) 981 validBucket := "testlistbucketevents" 982 983 // 1. Create bucket 984 if !setupBucket(validBucket, true, map[string]interface{}{"enabled": true}, nil, nil, assert, 200) { 985 return 986 } 987 988 // 2. List bucket events 989 type args struct { 990 bucketName string 991 } 992 tests := []struct { 993 name string 994 expectedStatus int 995 args args 996 }{ 997 { 998 name: "Valid bucket when listing events", 999 expectedStatus: 200, 1000 args: args{ 1001 bucketName: validBucket, 1002 }, 1003 }, 1004 { 1005 name: "Invalid bucket when listing events", 1006 expectedStatus: 500, 1007 args: args{ 1008 bucketName: "alksdjalksdjklasjdklasjdlkasjdkljaslkdjaskldjaklsjd", 1009 }, 1010 }, 1011 } 1012 for _, tt := range tests { 1013 t.Run(tt.name, func(_ *testing.T) { 1014 restResp, restErr := ListBucketEvents( 1015 tt.args.bucketName, 1016 ) 1017 assert.Nil(restErr) 1018 if restErr != nil { 1019 log.Println(restErr) 1020 return 1021 } 1022 finalResponse := inspectHTTPResponse(restResp) 1023 if restResp != nil { 1024 assert.Equal( 1025 tt.expectedStatus, 1026 restResp.StatusCode, 1027 finalResponse, 1028 ) 1029 } 1030 }) 1031 } 1032 } 1033 1034 func TestDeleteObjectsRetentionStatus(t *testing.T) { 1035 // Variables 1036 assert := assert.New(t) 1037 bucketName := "testdeleteobjectslegalholdstatus" 1038 fileName := "testdeleteobjectslegalholdstatus.txt" 1039 validPrefix := encodeBase64(fileName) 1040 1041 // 1. Create bucket 1042 if !setupBucket(bucketName, true, map[string]interface{}{"enabled": true}, nil, nil, assert, 200) { 1043 return 1044 } 1045 1046 // 2. Add object 1047 uploadResponse, uploadError := UploadAnObject( 1048 bucketName, 1049 fileName, 1050 ) 1051 assert.Nil(uploadError) 1052 if uploadError != nil { 1053 log.Println(uploadError) 1054 return 1055 } 1056 addObjRsp := inspectHTTPResponse(uploadResponse) 1057 if uploadResponse != nil { 1058 assert.Equal( 1059 200, 1060 uploadResponse.StatusCode, 1061 addObjRsp, 1062 ) 1063 } 1064 1065 // Get versionID 1066 listResponse, _ := ListObjects(bucketName, validPrefix, "true") 1067 bodyBytes, _ := io.ReadAll(listResponse.Body) 1068 listObjs := models.ListObjectsResponse{} 1069 err := json.Unmarshal(bodyBytes, &listObjs) 1070 if err != nil { 1071 log.Println(err) 1072 assert.Nil(err) 1073 } 1074 versionID := listObjs.Objects[0].VersionID 1075 1076 // 3. Put Objects Retention Status 1077 putResponse, putError := PutObjectsRetentionStatus( 1078 bucketName, 1079 validPrefix, 1080 versionID, 1081 "governance", 1082 "2033-01-11T23:59:59Z", 1083 false, 1084 ) 1085 if putError != nil { 1086 log.Println(putError) 1087 assert.Fail("Error putting the object retention status") 1088 } 1089 if putResponse != nil { 1090 assert.Equal( 1091 200, 1092 putResponse.StatusCode, 1093 inspectHTTPResponse(putResponse), 1094 ) 1095 } 1096 1097 type args struct { 1098 prefix string 1099 } 1100 tests := []struct { 1101 name string 1102 expectedStatus int 1103 args args 1104 }{ 1105 { 1106 name: "Valid prefix when deleting object's retention status", 1107 expectedStatus: 200, 1108 args: args{ 1109 prefix: validPrefix, 1110 }, 1111 }, 1112 { 1113 name: "Invalid prefix when deleting object's retention status", 1114 expectedStatus: 500, 1115 args: args{ 1116 prefix: "fakefile", 1117 }, 1118 }, 1119 } 1120 for _, tt := range tests { 1121 t.Run(tt.name, func(_ *testing.T) { 1122 // 4. Delete Objects Retention Status 1123 putResponse, putError := DeleteObjectsRetentionStatus( 1124 bucketName, 1125 tt.args.prefix, 1126 versionID, 1127 ) 1128 if putError != nil { 1129 log.Println(putError) 1130 assert.Fail("Error deleting the object retention status") 1131 } 1132 if putResponse != nil { 1133 assert.Equal( 1134 tt.expectedStatus, 1135 putResponse.StatusCode, 1136 inspectHTTPResponse(putResponse), 1137 ) 1138 } 1139 }) 1140 } 1141 } 1142 1143 func TestBucketSetPolicy(t *testing.T) { 1144 // Variables 1145 assert := assert.New(t) 1146 validBucketName := "testbucketsetpolicy" 1147 1148 // 1. Create bucket 1149 if !setupBucket(validBucketName, true, map[string]interface{}{"enabled": true}, nil, nil, assert, 200) { 1150 return 1151 } 1152 1153 // 2. Set a bucket's policy using table driven tests 1154 type args struct { 1155 bucketName string 1156 } 1157 tests := []struct { 1158 name string 1159 expectedStatus int 1160 args args 1161 }{ 1162 { 1163 name: "Valid bucket when setting a policy", 1164 expectedStatus: 200, 1165 args: args{ 1166 bucketName: validBucketName, 1167 }, 1168 }, 1169 { 1170 name: "Invalid bucket when setting a bucket", 1171 expectedStatus: 500, 1172 args: args{ 1173 bucketName: "wlkjsdkalsjdklajsdlkajsdlkajsdlkajsdklajsdkljaslkdjaslkdj", 1174 }, 1175 }, 1176 } 1177 for _, tt := range tests { 1178 t.Run(tt.name, func(_ *testing.T) { 1179 // Set Policy 1180 restResp, restErr := BucketSetPolicy( 1181 tt.args.bucketName, 1182 "PUBLIC", 1183 "", 1184 ) 1185 assert.Nil(restErr) 1186 if restErr != nil { 1187 log.Println(restErr) 1188 return 1189 } 1190 finalResponse := inspectHTTPResponse(restResp) 1191 if restResp != nil { 1192 assert.Equal( 1193 tt.expectedStatus, 1194 restResp.StatusCode, 1195 finalResponse, 1196 ) 1197 } 1198 }) 1199 } 1200 } 1201 1202 func TestRestoreObjectToASelectedVersion(t *testing.T) { 1203 // Variables 1204 assert := assert.New(t) 1205 bucketName := "testrestoreobjectstoselectedversion" 1206 fileName := "testrestoreobjectstoselectedversion.txt" 1207 validPrefix := encodeBase64(fileName) 1208 1209 // 1. Create bucket 1210 if !setupBucket(bucketName, true, map[string]interface{}{"enabled": true}, nil, nil, assert, 200) { 1211 return 1212 } 1213 1214 // 2. Add object 1215 uploadResponse, uploadError := UploadAnObject( 1216 bucketName, 1217 fileName, 1218 ) 1219 assert.Nil(uploadError) 1220 if uploadError != nil { 1221 log.Println(uploadError) 1222 return 1223 } 1224 addObjRsp := inspectHTTPResponse(uploadResponse) 1225 if uploadResponse != nil { 1226 assert.Equal( 1227 200, 1228 uploadResponse.StatusCode, 1229 addObjRsp, 1230 ) 1231 } 1232 1233 // 3. Get versionID 1234 listResponse, _ := ListObjects(bucketName, validPrefix, "true") 1235 bodyBytes, _ := io.ReadAll(listResponse.Body) 1236 listObjs := models.ListObjectsResponse{} 1237 err := json.Unmarshal(bodyBytes, &listObjs) 1238 if err != nil { 1239 log.Println(err) 1240 assert.Nil(err) 1241 } 1242 versionID := listObjs.Objects[0].VersionID 1243 1244 type args struct { 1245 prefix string 1246 } 1247 tests := []struct { 1248 name string 1249 expectedStatus int 1250 args args 1251 }{ 1252 { 1253 name: "Valid prefix when restoring object", 1254 expectedStatus: 200, 1255 args: args{ 1256 prefix: validPrefix, 1257 }, 1258 }, 1259 { 1260 name: "Invalid prefix when restoring object", 1261 expectedStatus: 500, 1262 args: args{ 1263 prefix: "fakefile", 1264 }, 1265 }, 1266 } 1267 for _, tt := range tests { 1268 t.Run(tt.name, func(_ *testing.T) { 1269 // 4. Restore Object to a selected version 1270 restResp, restErr := RestoreObjectToASelectedVersion( 1271 bucketName, 1272 tt.args.prefix, 1273 versionID, 1274 ) 1275 assert.Nil(restErr) 1276 if restErr != nil { 1277 log.Println(restErr) 1278 return 1279 } 1280 finalResponse := inspectHTTPResponse(restResp) 1281 if restResp != nil { 1282 assert.Equal( 1283 tt.expectedStatus, 1284 restResp.StatusCode, 1285 finalResponse, 1286 ) 1287 } 1288 }) 1289 } 1290 } 1291 1292 func TestPutBucketsTags(t *testing.T) { 1293 // Focused test for "Put Bucket's tags" endpoint 1294 1295 // 1. Create the bucket 1296 assert := assert.New(t) 1297 validBucketName := "testputbuckettags1" 1298 if !setupBucket(validBucketName, false, nil, nil, nil, assert, 200) { 1299 return 1300 } 1301 1302 type args struct { 1303 bucketName string 1304 } 1305 tests := []struct { 1306 name string 1307 expectedStatus int 1308 args args 1309 }{ 1310 { 1311 name: "Put a tag to a valid bucket", 1312 expectedStatus: 200, 1313 args: args{ 1314 bucketName: validBucketName, 1315 }, 1316 }, 1317 { 1318 name: "Put a tag to an invalid bucket", 1319 expectedStatus: 500, 1320 args: args{ 1321 bucketName: "invalidbucketname", 1322 }, 1323 }, 1324 } 1325 for _, tt := range tests { 1326 t.Run(tt.name, func(_ *testing.T) { 1327 // 2. Add a tag to the bucket 1328 tags := make(map[string]string) 1329 tags["tag2"] = "tag2" 1330 putBucketTagResponse, putBucketTagError := PutBucketsTags( 1331 tt.args.bucketName, tags) 1332 if putBucketTagError != nil { 1333 log.Println(putBucketTagError) 1334 assert.Fail("Error putting the bucket's tags") 1335 return 1336 } 1337 if putBucketTagResponse != nil { 1338 assert.Equal( 1339 tt.expectedStatus, putBucketTagResponse.StatusCode, 1340 inspectHTTPResponse(putBucketTagResponse)) 1341 } 1342 }) 1343 } 1344 } 1345 1346 func TestGetsTheMetadataOfAnObject(t *testing.T) { 1347 // Vars 1348 assert := assert.New(t) 1349 bucketName := "testgetsthemetadataofanobject" 1350 fileName := "testshareobjectonurl.txt" 1351 validPrefix := encodeBase64(fileName) 1352 tags := make(map[string]string) 1353 tags["tag"] = "testputobjecttagbucketonetagone" 1354 1355 // 1. Create the bucket 1356 if !setupBucket(bucketName, false, nil, nil, nil, assert, 200) { 1357 return 1358 } 1359 1360 // 2. Upload the object to the bucket 1361 uploadResponse, uploadError := UploadAnObject(bucketName, fileName) 1362 assert.Nil(uploadError) 1363 if uploadError != nil { 1364 log.Println(uploadError) 1365 return 1366 } 1367 if uploadResponse != nil { 1368 assert.Equal( 1369 200, 1370 uploadResponse.StatusCode, 1371 inspectHTTPResponse(uploadResponse), 1372 ) 1373 } 1374 1375 type args struct { 1376 prefix string 1377 } 1378 tests := []struct { 1379 name string 1380 expectedStatus int 1381 args args 1382 }{ 1383 { 1384 name: "Get metadata with valid prefix", 1385 expectedStatus: 200, 1386 args: args{ 1387 prefix: validPrefix, 1388 }, 1389 }, 1390 { 1391 name: "Get metadata with invalid prefix", 1392 expectedStatus: 500, 1393 args: args{ 1394 prefix: "invalidprefix", 1395 }, 1396 }, 1397 } 1398 for _, tt := range tests { 1399 t.Run(tt.name, func(_ *testing.T) { 1400 // 3. Get the metadata from an object 1401 getRsp, getErr := GetsTheMetadataOfAnObject( 1402 bucketName, tt.args.prefix) 1403 assert.Nil(getErr) 1404 if getErr != nil { 1405 log.Println(getErr) 1406 return 1407 } 1408 if getRsp != nil { 1409 assert.Equal( 1410 tt.expectedStatus, 1411 getRsp.StatusCode, 1412 inspectHTTPResponse(getRsp), 1413 ) 1414 } 1415 }) 1416 } 1417 } 1418 1419 func TestPutObjectsRetentionStatus(t *testing.T) { 1420 // Variables 1421 assert := assert.New(t) 1422 bucketName := "testputobjectsretentionstatus" 1423 fileName := "testputobjectsretentionstatus.txt" 1424 prefix := encodeBase64(fileName) 1425 1426 // 1. Create bucket 1427 if !setupBucket(bucketName, true, map[string]interface{}{"enabled": true}, nil, nil, assert, 200) { 1428 return 1429 } 1430 1431 // 2. Add object 1432 uploadResponse, uploadError := UploadAnObject( 1433 bucketName, 1434 fileName, 1435 ) 1436 assert.Nil(uploadError) 1437 if uploadError != nil { 1438 log.Println(uploadError) 1439 return 1440 } 1441 addObjRsp := inspectHTTPResponse(uploadResponse) 1442 if uploadResponse != nil { 1443 assert.Equal( 1444 200, 1445 uploadResponse.StatusCode, 1446 addObjRsp, 1447 ) 1448 } 1449 1450 // Get versionID 1451 listResponse, _ := ListObjects(bucketName, prefix, "true") 1452 bodyBytes, _ := io.ReadAll(listResponse.Body) 1453 listObjs := models.ListObjectsResponse{} 1454 err := json.Unmarshal(bodyBytes, &listObjs) 1455 if err != nil { 1456 log.Println(err) 1457 assert.Nil(err) 1458 } 1459 validVersionID := listObjs.Objects[0].VersionID 1460 1461 type args struct { 1462 versionID string 1463 } 1464 tests := []struct { 1465 name string 1466 expectedStatus int 1467 args args 1468 }{ 1469 { 1470 name: "Valid VersionID when putting object's retention status", 1471 expectedStatus: 200, 1472 args: args{ 1473 versionID: validVersionID, 1474 }, 1475 }, 1476 { 1477 name: "Invalid VersionID when putting object's retention status", 1478 expectedStatus: 500, 1479 args: args{ 1480 versionID: "*&^###Test1ThisMightBeInvalid555", 1481 }, 1482 }, 1483 } 1484 for _, tt := range tests { 1485 t.Run(tt.name, func(_ *testing.T) { 1486 // 3. Put Objects Legal Status 1487 putResponse, putError := PutObjectsRetentionStatus( 1488 bucketName, 1489 prefix, 1490 tt.args.versionID, 1491 "compliance", 1492 "2033-01-13T23:59:59Z", 1493 false, 1494 ) 1495 if putError != nil { 1496 log.Println(putError) 1497 assert.Fail("Error putting the object's retention status") 1498 } 1499 if putResponse != nil { 1500 assert.Equal( 1501 tt.expectedStatus, 1502 putResponse.StatusCode, 1503 inspectHTTPResponse(putResponse), 1504 ) 1505 } 1506 }) 1507 } 1508 } 1509 1510 func TestShareObjectOnURL(t *testing.T) { 1511 /* 1512 Test to share an object via URL 1513 */ 1514 1515 // Vars 1516 assert := assert.New(t) 1517 bucketName := "testshareobjectonurl" 1518 fileName := "testshareobjectonurl.txt" 1519 validPrefix := encodeBase64(fileName) 1520 tags := make(map[string]string) 1521 tags["tag"] = "testputobjecttagbucketonetagone" 1522 versionID := "null" 1523 1524 // 1. Create the bucket 1525 if !setupBucket(bucketName, false, nil, nil, nil, assert, 200) { 1526 return 1527 } 1528 1529 // 2. Upload the object to the bucket 1530 uploadResponse, uploadError := UploadAnObject(bucketName, fileName) 1531 assert.Nil(uploadError) 1532 if uploadError != nil { 1533 log.Println(uploadError) 1534 return 1535 } 1536 if uploadResponse != nil { 1537 assert.Equal( 1538 200, 1539 uploadResponse.StatusCode, 1540 inspectHTTPResponse(uploadResponse), 1541 ) 1542 } 1543 1544 type args struct { 1545 prefix string 1546 } 1547 tests := []struct { 1548 name string 1549 expectedStatus int 1550 args args 1551 }{ 1552 { 1553 name: "Share File with valid prefix", 1554 expectedStatus: 200, 1555 args: args{ 1556 prefix: validPrefix, 1557 }, 1558 }, 1559 { 1560 name: "Share file with invalid prefix", 1561 expectedStatus: 500, 1562 args: args{ 1563 prefix: "invalidprefix", 1564 }, 1565 }, 1566 } 1567 for _, tt := range tests { 1568 t.Run(tt.name, func(_ *testing.T) { 1569 // 3. Share the object on a URL 1570 shareResponse, shareError := SharesAnObjectOnAUrl(bucketName, tt.args.prefix, versionID, "604800s") 1571 assert.Nil(shareError) 1572 if shareError != nil { 1573 log.Println(shareError) 1574 return 1575 } 1576 finalResponse := inspectHTTPResponse(shareResponse) 1577 if shareResponse != nil { 1578 assert.Equal( 1579 tt.expectedStatus, 1580 shareResponse.StatusCode, 1581 finalResponse, 1582 ) 1583 } 1584 }) 1585 } 1586 } 1587 1588 func TestListObjects(t *testing.T) { 1589 /* 1590 To test list objects end point. 1591 */ 1592 1593 // Test's variables 1594 assert := assert.New(t) 1595 bucketName := "testlistobjecttobucket1" 1596 fileName := "testlistobjecttobucket1.txt" 1597 1598 // 1. Create the bucket 1599 if !setupBucket(bucketName, false, nil, nil, nil, assert, 200) { 1600 return 1601 } 1602 1603 // 2. Upload the object to the bucket 1604 uploadResponse, uploadError := UploadAnObject(bucketName, fileName) 1605 assert.Nil(uploadError) 1606 if uploadError != nil { 1607 log.Println(uploadError) 1608 return 1609 } 1610 if uploadResponse != nil { 1611 assert.Equal(200, uploadResponse.StatusCode, 1612 inspectHTTPResponse(uploadResponse)) 1613 } 1614 1615 // 3. List the object 1616 listResponse, listError := ListObjects(bucketName, "", "false") 1617 assert.Nil(listError) 1618 if listError != nil { 1619 log.Println(listError) 1620 return 1621 } 1622 finalResponse := inspectHTTPResponse(listResponse) 1623 if listResponse != nil { 1624 assert.Equal(200, listResponse.StatusCode, 1625 finalResponse) 1626 } 1627 1628 // 4. Verify the object was listed 1629 assert.True( 1630 strings.Contains(finalResponse, "testlistobjecttobucket1"), 1631 finalResponse) 1632 } 1633 1634 func TestDeleteObject(t *testing.T) { 1635 /* 1636 Test to delete an object from a given bucket. 1637 */ 1638 1639 // Variables 1640 assert := assert.New(t) 1641 bucketName := "testdeleteobjectbucket1" 1642 fileName := "testdeleteobjectfile" 1643 numberOfFiles := 2 1644 1645 // 1. Create bucket 1646 if !setupBucket(bucketName, true, map[string]interface{}{"enabled": true}, nil, nil, assert, 200) { 1647 return 1648 } 1649 1650 // 2. Add two objects to the bucket created. 1651 for i := 1; i <= numberOfFiles; i++ { 1652 uploadResponse, uploadError := UploadAnObject( 1653 bucketName, fileName+strconv.Itoa(i)+".txt") 1654 assert.Nil(uploadError) 1655 if uploadError != nil { 1656 log.Println(uploadError) 1657 return 1658 } 1659 if uploadResponse != nil { 1660 assert.Equal(200, uploadResponse.StatusCode, 1661 inspectHTTPResponse(uploadResponse)) 1662 } 1663 } 1664 1665 objPathFull := fileName + "1.txt" // would be encoded in DeleteObject util method. 1666 // 3. Delete only one object from the bucket. 1667 deleteResponse, deleteError := DeleteObject(bucketName, objPathFull, false, false) 1668 assert.Nil(deleteError) 1669 if deleteError != nil { 1670 log.Println(deleteError) 1671 return 1672 } 1673 if deleteResponse != nil { 1674 assert.Equal(200, deleteResponse.StatusCode, 1675 inspectHTTPResponse(deleteResponse)) 1676 } 1677 1678 // 4. List the objects in the bucket and make sure the object is gone 1679 listResponse, listError := ListObjects(bucketName, "", "false") 1680 assert.Nil(listError) 1681 if listError != nil { 1682 log.Println(listError) 1683 return 1684 } 1685 finalResponse := inspectHTTPResponse(listResponse) 1686 if listResponse != nil { 1687 assert.Equal(200, listResponse.StatusCode, 1688 finalResponse) 1689 } 1690 // Expected only one file: "testdeleteobjectfile2.txt" 1691 // "testdeleteobjectfile1.txt" should be gone by now. 1692 assert.True( 1693 strings.Contains( 1694 finalResponse, 1695 "testdeleteobjectfile2.txt"), finalResponse) // Still there 1696 assert.False( 1697 strings.Contains( 1698 finalResponse, 1699 "testdeleteobjectfile1.txt"), finalResponse) // Gone 1700 } 1701 1702 func TestUploadObjectToBucket(t *testing.T) { 1703 /* 1704 Function to test the upload of an object to a bucket. 1705 */ 1706 1707 // Test's variables 1708 assert := assert.New(t) 1709 bucketName := "testuploadobjecttobucket1" 1710 fileName := "sample.txt" 1711 1712 // 1. Create the bucket 1713 if !setupBucket(bucketName, false, nil, nil, nil, assert, 200) { 1714 return 1715 } 1716 1717 // 2. Upload the object to the bucket 1718 uploadResponse, uploadError := UploadAnObject(bucketName, fileName) 1719 assert.Nil(uploadError) 1720 if uploadError != nil { 1721 log.Println(uploadError) 1722 return 1723 } 1724 1725 // 3. Verify the object was uploaded 1726 finalResponse := inspectHTTPResponse(uploadResponse) 1727 if uploadResponse != nil { 1728 assert.Equal(200, uploadResponse.StatusCode, finalResponse) 1729 } 1730 } 1731 1732 func TestDownloadObject(t *testing.T) { 1733 /* 1734 Test to download an object from a given bucket. 1735 */ 1736 1737 // Vars 1738 assert := assert.New(t) 1739 bucketName := "testdownloadobjbucketone" 1740 fileName := "testdownloadobjectfilenameone" 1741 path := encodeBase64(fileName) 1742 workingDirectory, getWdErr := os.Getwd() 1743 if getWdErr != nil { 1744 assert.Fail("Couldn't get the directory") 1745 } 1746 1747 // 1. Create the bucket 1748 if !setupBucket(bucketName, true, map[string]interface{}{"enabled": true}, nil, nil, assert, 200) { 1749 return 1750 } 1751 1752 // 2. Upload an object to the bucket 1753 uploadResponse, uploadError := UploadAnObject(bucketName, fileName) 1754 assert.Nil(uploadError) 1755 if uploadError != nil { 1756 log.Println(uploadError) 1757 return 1758 } 1759 if uploadResponse != nil { 1760 assert.Equal( 1761 200, 1762 uploadResponse.StatusCode, 1763 inspectHTTPResponse(uploadResponse), 1764 ) 1765 } 1766 1767 // 3. Download the object from the bucket 1768 downloadResponse, downloadError := DownloadObject(bucketName, path) 1769 assert.Nil(downloadError) 1770 if downloadError != nil { 1771 log.Println(downloadError) 1772 assert.Fail("Error downloading the object") 1773 return 1774 } 1775 finalResponse := inspectHTTPResponse(downloadResponse) 1776 if downloadResponse != nil { 1777 assert.Equal( 1778 200, 1779 downloadResponse.StatusCode, 1780 finalResponse, 1781 ) 1782 } 1783 1784 // 4. Verify the file was downloaded 1785 files, err := os.ReadDir(workingDirectory) 1786 if err != nil { 1787 log.Fatal(err) 1788 } 1789 for _, file := range files { 1790 fmt.Println(file.Name(), file.IsDir()) 1791 } 1792 if _, err := os.Stat(workingDirectory); errors.Is(err, os.ErrNotExist) { 1793 // path/to/whatever does not exist 1794 assert.Fail("File wasn't downloaded") 1795 } 1796 } 1797 1798 func TestDeleteMultipleObjects(t *testing.T) { 1799 /* 1800 Function to test the deletion of multiple objects from a given bucket. 1801 */ 1802 1803 // Variables 1804 assert := assert.New(t) 1805 bucketName := "testdeletemultipleobjsbucket1" 1806 numberOfFiles := 5 1807 fileName := "testdeletemultipleobjs" 1808 1809 // 1. Create a bucket for this particular test 1810 if !setupBucket(bucketName, false, nil, nil, nil, assert, 200) { 1811 return 1812 } 1813 1814 // 2. Add couple of objects to this bucket 1815 for i := 1; i <= numberOfFiles; i++ { 1816 uploadResponse, uploadError := UploadAnObject( 1817 bucketName, fileName+strconv.Itoa(i)+".txt") 1818 assert.Nil(uploadError) 1819 if uploadError != nil { 1820 log.Println(uploadError) 1821 return 1822 } 1823 if uploadResponse != nil { 1824 assert.Equal(200, uploadResponse.StatusCode, 1825 inspectHTTPResponse(uploadResponse)) 1826 } 1827 } 1828 1829 // Prepare the files for deletion 1830 files := make([]map[string]interface{}, numberOfFiles) 1831 for i := 1; i <= numberOfFiles; i++ { 1832 files[i-1] = map[string]interface{}{ 1833 "path": fileName + strconv.Itoa(i) + ".txt", 1834 "versionID": "", 1835 "recursive": false, 1836 } 1837 } 1838 1839 // 3. Delete these objects all at once 1840 deleteResponse, deleteError := DeleteMultipleObjects( 1841 bucketName, 1842 files, 1843 ) 1844 assert.Nil(deleteError) 1845 if deleteError != nil { 1846 log.Println(deleteError) 1847 return 1848 } 1849 if deleteResponse != nil { 1850 assert.Equal(200, deleteResponse.StatusCode, 1851 inspectHTTPResponse(deleteResponse)) 1852 } 1853 1854 // 4. List the objects, empty list is expected! 1855 listResponse, listError := ListObjects(bucketName, "", "false") 1856 assert.Nil(listError) 1857 if listError != nil { 1858 log.Println(listError) 1859 return 1860 } 1861 finalResponse := inspectHTTPResponse(listResponse) 1862 if listResponse != nil { 1863 assert.Equal(200, listResponse.StatusCode, 1864 finalResponse) 1865 } 1866 1867 // 5. Verify empty list is obtained as we deleted all the objects 1868 expected := "Http Response: {\"objects\":null}\n" 1869 assert.Equal(expected, finalResponse, finalResponse) 1870 } 1871 1872 func TestPutObjectTag(t *testing.T) { 1873 /* 1874 Test to put a tag to an object 1875 */ 1876 1877 // Vars 1878 assert := assert.New(t) 1879 bucketName := "testputobjecttagbucketone" 1880 fileName := "testputobjecttagbucketone.txt" 1881 path := encodeBase64(fileName) 1882 tags := make(map[string]string) 1883 tags["tag"] = "testputobjecttagbucketonetagone" 1884 versionID := "null" 1885 1886 // 1. Create the bucket 1887 if !setupBucket(bucketName, false, nil, nil, nil, assert, 200) { 1888 return 1889 } 1890 1891 // 2. Upload the object to the bucket 1892 uploadResponse, uploadError := UploadAnObject(bucketName, fileName) 1893 assert.Nil(uploadError) 1894 if uploadError != nil { 1895 log.Println(uploadError) 1896 return 1897 } 1898 if uploadResponse != nil { 1899 assert.Equal( 1900 200, 1901 uploadResponse.StatusCode, 1902 inspectHTTPResponse(uploadResponse), 1903 ) 1904 } 1905 1906 // 3. Put a tag to the object 1907 putTagResponse, putTagError := PutObjectTags( 1908 bucketName, path, tags, versionID) 1909 assert.Nil(putTagError) 1910 if putTagError != nil { 1911 log.Println(putTagError) 1912 return 1913 } 1914 putObjectTagresult := inspectHTTPResponse(putTagResponse) 1915 if putTagResponse != nil { 1916 assert.Equal( 1917 200, putTagResponse.StatusCode, putObjectTagresult) 1918 } 1919 1920 // 4. Verify the object's tag is set 1921 listResponse, listError := ListObjects(bucketName, path, "false") 1922 assert.Nil(listError) 1923 if listError != nil { 1924 log.Println(listError) 1925 return 1926 } 1927 finalResponse := inspectHTTPResponse(listResponse) 1928 if listResponse != nil { 1929 assert.Equal(200, listResponse.StatusCode, 1930 finalResponse) 1931 } 1932 assert.True( 1933 strings.Contains(finalResponse, tags["tag"]), 1934 finalResponse) 1935 } 1936 1937 func TestBucketRetention(t *testing.T) { 1938 /* 1939 To test bucket retention feature 1940 */ 1941 1942 // 1. Create the bucket with 2 years validity retention 1943 assert := assert.New(t) 1944 /* 1945 { 1946 "name":"setbucketretention1", 1947 "versioning":true, 1948 "locking":true, 1949 "retention": 1950 { 1951 "mode":"compliance", 1952 "unit":"years", 1953 "validity":2 1954 } 1955 } 1956 */ 1957 retention := make(map[string]interface{}) 1958 retention["mode"] = "compliance" 1959 retention["unit"] = "years" 1960 retention["validity"] = 2 1961 if !setupBucket("setbucketretention1", true, map[string]interface{}{"enabled": true}, nil, retention, assert, 200) { 1962 return 1963 } 1964 1965 // 2. Set the bucket's retention from 2 years to 3 years 1966 setBucketRetentionResponse, setBucketRetentionError := SetBucketRetention( 1967 "setbucketretention1", 1968 "compliance", 1969 "years", 1970 3, 1971 ) 1972 assert.Nil(setBucketRetentionError) 1973 if setBucketRetentionError != nil { 1974 log.Println(setBucketRetentionError) 1975 assert.Fail("Error setting the bucket retention") 1976 return 1977 } 1978 if setBucketRetentionResponse != nil { 1979 assert.Equal(200, setBucketRetentionResponse.StatusCode, 1980 inspectHTTPResponse(setBucketRetentionResponse)) 1981 } 1982 1983 // 3. Verify the bucket's retention was properly set. 1984 getBucketRetentionResponse, getBucketRetentionError := GetBucketRetention( 1985 "setbucketretention1", 1986 ) 1987 assert.Nil(getBucketRetentionError) 1988 if getBucketRetentionError != nil { 1989 log.Println(getBucketRetentionError) 1990 assert.Fail("Error getting the bucket's retention") 1991 return 1992 } 1993 finalResponse := inspectHTTPResponse(getBucketRetentionResponse) 1994 if getBucketRetentionResponse != nil { 1995 assert.Equal( 1996 200, 1997 getBucketRetentionResponse.StatusCode, 1998 finalResponse, 1999 ) 2000 } 2001 expected := "Http Response: {\"mode\":\"compliance\",\"unit\":\"years\",\"validity\":3}\n" 2002 assert.Equal(expected, finalResponse, finalResponse) 2003 } 2004 2005 func TestBucketInformationGenericErrorResponse(t *testing.T) { 2006 /* 2007 Test Bucket Info End Point with a Generic Error Response. 2008 */ 2009 2010 // 1. Create the bucket 2011 assert := assert.New(t) 2012 if !setupBucket("bucketinformation2", false, nil, nil, nil, assert, 200) { 2013 return 2014 } 2015 2016 // 2. Add a tag to the bucket 2017 tags := make(map[string]string) 2018 tags["tag2"] = "tag2" 2019 putBucketTagResponse, putBucketTagError := PutBucketsTags( 2020 "bucketinformation2", tags) 2021 if putBucketTagError != nil { 2022 log.Println(putBucketTagError) 2023 assert.Fail("Error putting the bucket's tags") 2024 return 2025 } 2026 if putBucketTagResponse != nil { 2027 assert.Equal( 2028 200, putBucketTagResponse.StatusCode, 2029 inspectHTTPResponse(putBucketTagResponse)) 2030 } 2031 2032 // 3. Get the information 2033 bucketInfoResponse, bucketInfoError := BucketInfo("bucketinformation3") 2034 if bucketInfoError != nil { 2035 log.Println(bucketInfoError) 2036 assert.Fail("Error getting the bucket information") 2037 return 2038 } 2039 finalResponse := inspectHTTPResponse(bucketInfoResponse) 2040 if bucketInfoResponse != nil { 2041 assert.Equal(200, bucketInfoResponse.StatusCode) 2042 } 2043 2044 // 4. Verify the information 2045 // Since bucketinformation3 hasn't been created, then it is expected that 2046 // tag2 is not part of the response, this is why assert.False is used. 2047 assert.False(strings.Contains(finalResponse, "tag2"), finalResponse) 2048 } 2049 2050 func TestBucketInformationSuccessfulResponse(t *testing.T) { 2051 /* 2052 Test Bucket Info End Point with a Successful Response. 2053 */ 2054 2055 // 1. Create the bucket 2056 assert := assert.New(t) 2057 if !setupBucket("bucketinformation1", false, nil, nil, nil, assert, 200) { 2058 return 2059 } 2060 2061 // 2. Add a tag to the bucket 2062 tags := make(map[string]string) 2063 tags["tag1"] = "tag1" 2064 putBucketTagResponse, putBucketTagError := PutBucketsTags( 2065 "bucketinformation1", tags) 2066 if putBucketTagError != nil { 2067 log.Println(putBucketTagError) 2068 assert.Fail("Error putting the bucket's tags") 2069 return 2070 } 2071 if putBucketTagResponse != nil { 2072 assert.Equal( 2073 200, putBucketTagResponse.StatusCode, 2074 inspectHTTPResponse(putBucketTagResponse)) 2075 } 2076 2077 // 3. Get the information 2078 bucketInfoResponse, bucketInfoError := BucketInfo("bucketinformation1") 2079 if bucketInfoError != nil { 2080 log.Println(bucketInfoError) 2081 assert.Fail("Error getting the bucket information") 2082 return 2083 } 2084 debugResponse := inspectHTTPResponse(bucketInfoResponse) // call it once 2085 if bucketInfoResponse != nil { 2086 assert.Equal(200, bucketInfoResponse.StatusCode, 2087 debugResponse) 2088 } 2089 fmt.Println(debugResponse) 2090 2091 // 4. Verify the information 2092 assert.True( 2093 strings.Contains(debugResponse, "bucketinformation1"), 2094 inspectHTTPResponse(bucketInfoResponse)) 2095 assert.True( 2096 strings.Contains(debugResponse, "tag1"), 2097 inspectHTTPResponse(bucketInfoResponse)) 2098 } 2099 2100 func TestDeleteBucket(t *testing.T) { 2101 /* 2102 Test to delete a bucket 2103 */ 2104 assert := assert.New(t) 2105 type args struct { 2106 bucketName string 2107 createBucketName string 2108 } 2109 tests := []struct { 2110 name string 2111 args args 2112 expectedStatus int 2113 }{ 2114 { 2115 name: "Delete a bucket", 2116 expectedStatus: 204, 2117 args: args{ 2118 bucketName: "testdeletebucket1", 2119 createBucketName: "testdeletebucket1", 2120 }, 2121 }, { 2122 name: "Delete invalid bucket", 2123 expectedStatus: 404, 2124 args: args{ 2125 bucketName: "nonexistingbucket", 2126 createBucketName: "", 2127 }, 2128 }, 2129 } 2130 2131 // Initialize minio client object. 2132 minioClient, err := minio.New("localhost:9000", &minio.Options{ 2133 Creds: credentials.NewStaticV4("minioadmin", "minioadmin", ""), 2134 Secure: false, 2135 }) 2136 if err != nil { 2137 log.Fatalln(err) 2138 } 2139 2140 for _, tt := range tests { 2141 t.Run(tt.name, func(_ *testing.T) { 2142 // Create bucket if needed for the test 2143 if tt.args.createBucketName != "" { 2144 if err := minioClient.MakeBucket(context.Background(), tt.args.createBucketName, minio.MakeBucketOptions{}); err != nil { 2145 assert.Failf("Failed to create bucket", "Could not create bucket %s: %v", tt.args.createBucketName, err) 2146 } 2147 } 2148 2149 // Delete the bucket 2150 deleteBucketResponse, deleteBucketError := DeleteBucket(tt.args.bucketName) 2151 assert.Nil(deleteBucketError) 2152 if deleteBucketResponse != nil { 2153 assert.Equal( 2154 tt.expectedStatus, deleteBucketResponse.StatusCode, "Status Code is incorrect") 2155 } 2156 }) 2157 } 2158 } 2159 2160 func TestListBuckets(t *testing.T) { 2161 /* 2162 Test the list of buckets without query parameters. 2163 */ 2164 2165 assert := assert.New(t) 2166 2167 // 1. Create buckets 2168 numberOfBuckets := 3 2169 for i := 1; i <= numberOfBuckets; i++ { 2170 if !setupBucket("testlistbuckets"+strconv.Itoa(i), false, nil, nil, nil, assert, 200) { 2171 return 2172 } 2173 } 2174 2175 // Waiting to retrieve the new list of buckets 2176 time.Sleep(3 * time.Second) 2177 2178 // 2. List buckets 2179 listBucketsResponse, listBucketsError := ListBuckets() 2180 assert.Nil(listBucketsError) 2181 assert.NotNil(listBucketsResponse) 2182 assert.NotNil(listBucketsResponse.Body) 2183 // 3. Verify list of buckets 2184 b, _ := io.ReadAll(listBucketsResponse.Body) 2185 assert.Equal(200, listBucketsResponse.StatusCode, 2186 "Status Code is incorrect: "+string(b)) 2187 for i := 1; i <= numberOfBuckets; i++ { 2188 assert.True(strings.Contains(string(b), 2189 "testlistbuckets"+strconv.Itoa(i))) 2190 } 2191 } 2192 2193 func TestBucketsGet(t *testing.T) { 2194 assert := assert.New(t) 2195 2196 client := &http.Client{ 2197 Timeout: 2 * time.Second, 2198 } 2199 2200 // get list of buckets 2201 request, err := http.NewRequest("GET", "http://localhost:9090/api/v1/buckets", nil) 2202 if err != nil { 2203 log.Println(err) 2204 return 2205 } 2206 2207 request.Header.Add("Cookie", fmt.Sprintf("token=%s", token)) 2208 2209 response, err := client.Do(request) 2210 assert.Nil(err) 2211 if err != nil { 2212 log.Println(err) 2213 return 2214 } 2215 2216 if response != nil { 2217 assert.Equal(200, response.StatusCode, "Status Code is incorrect") 2218 bodyBytes, _ := io.ReadAll(response.Body) 2219 2220 listBuckets := models.ListBucketsResponse{} 2221 err = json.Unmarshal(bodyBytes, &listBuckets) 2222 if err != nil { 2223 log.Println(err) 2224 assert.Nil(err) 2225 } 2226 2227 assert.Greater(len(listBuckets.Buckets), 0, "No bucket was returned") 2228 assert.Greater(listBuckets.Total, int64(0), "Total buckets is 0") 2229 2230 } 2231 } 2232 2233 func TestBucketVersioning(t *testing.T) { 2234 assert := assert.New(t) 2235 2236 client := &http.Client{ 2237 Timeout: 2 * time.Second, 2238 } 2239 2240 request, err := http.NewRequest("GET", "http://localhost:9090/api/v1/session", nil) 2241 if err != nil { 2242 log.Println(err) 2243 return 2244 } 2245 2246 request.Header.Add("Cookie", fmt.Sprintf("token=%s", token)) 2247 2248 response, err := client.Do(request) 2249 assert.Nil(err) 2250 if err != nil { 2251 log.Println(err) 2252 return 2253 } 2254 var distributedSystem bool 2255 2256 if response != nil { 2257 2258 bodyBytes, _ := io.ReadAll(response.Body) 2259 2260 sessionResponse := models.SessionResponse{} 2261 err = json.Unmarshal(bodyBytes, &sessionResponse) 2262 if err != nil { 2263 log.Println(err) 2264 } 2265 2266 distributedSystem = sessionResponse.DistributedMode 2267 2268 } 2269 2270 requestDataVersioning := map[string]interface{}{ 2271 "name": "test2", 2272 "versioning": true, 2273 "locking": false, 2274 } 2275 2276 requestDataJSON, _ := json.Marshal(requestDataVersioning) 2277 2278 requestDataBody := bytes.NewReader(requestDataJSON) 2279 2280 if !setupBucket("test2", true, nil, nil, nil, assert, 200) { 2281 return 2282 } 2283 2284 // Read the HTTP Response and make sure we get: {"is_versioned":true} 2285 getVersioningResult, getVersioningError := GetBucketVersioning("test2") 2286 assert.Nil(getVersioningError) 2287 if getVersioningError != nil { 2288 log.Println(getVersioningError) 2289 return 2290 } 2291 if getVersioningResult != nil { 2292 assert.Equal( 2293 200, getVersioningResult.StatusCode, "Status Code is incorrect") 2294 } 2295 bodyBytes, _ := io.ReadAll(getVersioningResult.Body) 2296 structBucketRepl := models.BucketVersioningResponse{ 2297 ExcludeFolders: false, 2298 ExcludedPrefixes: nil, 2299 MFADelete: "", 2300 Status: "", 2301 } 2302 err = json.Unmarshal(bodyBytes, &structBucketRepl) 2303 if err != nil { 2304 log.Println(err) 2305 assert.Nil(err) 2306 } 2307 assert.Equal( 2308 structBucketRepl.Status, 2309 "Enabled", 2310 structBucketRepl.Status, 2311 ) 2312 2313 fmt.Println("Versioned bucket creation test status:", response.Status) 2314 if distributedSystem { 2315 assert.Equal(200, response.StatusCode, "Versioning test Status Code is incorrect - bucket failed to create") 2316 } else { 2317 assert.NotEqual(200, response.StatusCode, "Versioning test Status Code is incorrect - versioned bucket created on non-distributed system") 2318 } 2319 2320 request, err = http.NewRequest("DELETE", "http://localhost:9090/api/v1/buckets/test2", requestDataBody) 2321 if err != nil { 2322 log.Println(err) 2323 return 2324 } 2325 2326 request.Header.Add("Cookie", fmt.Sprintf("token=%s", token)) 2327 request.Header.Add("Content-Type", "application/json") 2328 2329 response, err = client.Do(request) 2330 if err != nil { 2331 log.Println(err) 2332 return 2333 } 2334 2335 if response != nil { 2336 fmt.Println("DELETE StatusCode:", response.StatusCode) 2337 } 2338 } 2339 2340 func TestSetBucketTags(t *testing.T) { 2341 assert := assert.New(t) 2342 2343 client := &http.Client{ 2344 Timeout: 2 * time.Second, 2345 } 2346 2347 // put bucket 2348 if !setupBucket("test4", false, nil, nil, nil, assert, 200) { 2349 return 2350 } 2351 2352 requestDataTags := map[string]interface{}{ 2353 "tags": map[string]interface{}{ 2354 "test": "TAG", 2355 }, 2356 } 2357 2358 requestTagsJSON, _ := json.Marshal(requestDataTags) 2359 2360 requestTagsBody := bytes.NewBuffer(requestTagsJSON) 2361 2362 request, err := http.NewRequest(http.MethodPut, "http://localhost:9090/api/v1/buckets/test4/tags", requestTagsBody) 2363 request.Close = true 2364 if err != nil { 2365 log.Println(err) 2366 return 2367 } 2368 2369 request.Header.Add("Cookie", fmt.Sprintf("token=%s", token)) 2370 request.Header.Add("Content-Type", "application/json") 2371 2372 _, err = client.Do(request) 2373 assert.Nil(err) 2374 if err != nil { 2375 log.Println(err) 2376 return 2377 } 2378 2379 // get bucket 2380 request, err = http.NewRequest("GET", "http://localhost:9090/api/v1/buckets/test4", nil) 2381 request.Close = true 2382 if err != nil { 2383 log.Println(err) 2384 return 2385 } 2386 2387 request.Header.Add("Cookie", fmt.Sprintf("token=%s", token)) 2388 request.Header.Add("Content-Type", "application/json") 2389 2390 response, err := client.Do(request) 2391 assert.Nil(err) 2392 if err != nil { 2393 log.Println(err) 2394 return 2395 } 2396 2397 bodyBytes, _ := io.ReadAll(response.Body) 2398 2399 bucket := models.Bucket{} 2400 err = json.Unmarshal(bodyBytes, &bucket) 2401 if err != nil { 2402 log.Println(err) 2403 } 2404 2405 assert.Equal("TAG", bucket.Details.Tags["test"], "Failed to add tag") 2406 } 2407 2408 func TestGetBucket(t *testing.T) { 2409 assert := assert.New(t) 2410 2411 client := &http.Client{ 2412 Timeout: 2 * time.Second, 2413 } 2414 2415 if !setupBucket("test3", false, nil, nil, nil, assert, 200) { 2416 return 2417 } 2418 2419 // get bucket 2420 request, err := http.NewRequest("GET", "http://localhost:9090/api/v1/buckets/test3", nil) 2421 if err != nil { 2422 log.Println(err) 2423 return 2424 } 2425 2426 request.Header.Add("Cookie", fmt.Sprintf("token=%s", token)) 2427 request.Header.Add("Content-Type", "application/json") 2428 2429 response, err := client.Do(request) 2430 assert.Nil(err) 2431 if err != nil { 2432 log.Println(err) 2433 return 2434 } 2435 2436 if response != nil { 2437 assert.Equal(200, response.StatusCode, "Status Code is incorrect") 2438 } 2439 } 2440 2441 func TestAddBucket(t *testing.T) { 2442 assert := assert.New(t) 2443 type args struct { 2444 bucketName string 2445 } 2446 tests := []struct { 2447 name string 2448 args args 2449 expectedStatus int 2450 }{ 2451 { 2452 name: "Add Bucket with valid name", 2453 expectedStatus: 200, 2454 args: args{ 2455 bucketName: "test1", 2456 }, 2457 }, 2458 { 2459 name: "Add Bucket with invalid name", 2460 expectedStatus: 500, 2461 args: args{ 2462 bucketName: "*&^###Test1ThisMightBeInvalid555", 2463 }, 2464 }, 2465 } 2466 for _, tt := range tests { 2467 t.Run(tt.name, func(_ *testing.T) { 2468 if !setupBucket(tt.args.bucketName, false, nil, nil, nil, assert, tt.expectedStatus) { 2469 return 2470 } 2471 }) 2472 } 2473 } 2474 2475 func CreateBucketEvent(bucketName string, ignoreExisting bool, arn, prefix, suffix string, events []string) (*http.Response, error) { 2476 /* 2477 Helper function to create bucket event 2478 POST: /buckets/{bucket_name}/events 2479 { 2480 "configuration": 2481 { 2482 "arn":"arn:minio:sqs::_:postgresql", 2483 "events":["put"], 2484 "prefix":"", 2485 "suffix":"" 2486 }, 2487 "ignoreExisting":true 2488 } 2489 */ 2490 configuration := map[string]interface{}{ 2491 "arn": arn, 2492 "events": events, 2493 "prefix": prefix, 2494 "suffix": suffix, 2495 } 2496 requestDataAdd := map[string]interface{}{ 2497 "configuration": configuration, 2498 "ignoreExisting": ignoreExisting, 2499 } 2500 requestDataJSON, _ := json.Marshal(requestDataAdd) 2501 requestDataBody := bytes.NewReader(requestDataJSON) 2502 request, err := http.NewRequest( 2503 "POST", 2504 "http://localhost:9090/api/v1/buckets/"+bucketName+"/events", 2505 requestDataBody, 2506 ) 2507 if err != nil { 2508 log.Println(err) 2509 } 2510 request.Header.Add("Cookie", fmt.Sprintf("token=%s", token)) 2511 request.Header.Add("Content-Type", "application/json") 2512 client := &http.Client{ 2513 Timeout: 2 * time.Second, 2514 } 2515 response, err := client.Do(request) 2516 return response, err 2517 } 2518 2519 func DeleteBucketEvent(bucketName, arn string, events []string, prefix, suffix string) (*http.Response, error) { 2520 /* 2521 Helper function to test Delete Bucket Event 2522 DELETE: /buckets/{bucket_name}/events/{arn} 2523 { 2524 "events":["put"], 2525 "prefix":"", 2526 "suffix":"" 2527 } 2528 */ 2529 requestDataAdd := map[string]interface{}{ 2530 "events": events, 2531 "prefix": prefix, 2532 "suffix": suffix, 2533 } 2534 requestDataJSON, _ := json.Marshal(requestDataAdd) 2535 requestDataBody := bytes.NewReader(requestDataJSON) 2536 request, err := http.NewRequest( 2537 "DELETE", 2538 "http://localhost:9090/api/v1/buckets/"+bucketName+"/events/"+arn, 2539 requestDataBody, 2540 ) 2541 if err != nil { 2542 log.Println(err) 2543 } 2544 request.Header.Add("Cookie", fmt.Sprintf("token=%s", token)) 2545 request.Header.Add("Content-Type", "application/json") 2546 client := &http.Client{ 2547 Timeout: 2 * time.Second, 2548 } 2549 response, err := client.Do(request) 2550 return response, err 2551 } 2552 2553 func TestDeleteBucketEvent(t *testing.T) { 2554 // Variables 2555 assert := assert.New(t) 2556 2557 // 1. Add postgres notification 2558 response, err := NotifyPostgres() 2559 finalResponse := inspectHTTPResponse(response) 2560 assert.Nil(err) 2561 if err != nil { 2562 log.Println(err) 2563 assert.Fail(finalResponse) 2564 return 2565 } 2566 if response != nil { 2567 assert.Equal(200, response.StatusCode, finalResponse) 2568 } 2569 2570 // 2. Restart the system 2571 restartResponse, restartError := RestartService() 2572 assert.Nil(restartError) 2573 if restartError != nil { 2574 log.Println(restartError) 2575 return 2576 } 2577 addObjRsp := inspectHTTPResponse(restartResponse) 2578 if restartResponse != nil { 2579 assert.Equal( 2580 204, 2581 restartResponse.StatusCode, 2582 addObjRsp, 2583 ) 2584 } 2585 2586 // 3. Subscribe bucket to event 2587 events := make([]string, 1) 2588 events[0] = "put" 2589 eventResponse, eventError := CreateBucketEvent( 2590 "testputobjectslegalholdstatus", // bucket name 2591 true, // ignore existing param 2592 "arn:minio:sqs::_:postgresql", // arn 2593 "", // prefix 2594 "", // suffix 2595 events, // events 2596 ) 2597 assert.Nil(eventError) 2598 if eventError != nil { 2599 log.Println(eventError) 2600 return 2601 } 2602 finalResponseEvent := inspectHTTPResponse(eventResponse) 2603 if eventResponse != nil { 2604 assert.Equal( 2605 201, 2606 eventResponse.StatusCode, 2607 finalResponseEvent, 2608 ) 2609 } 2610 2611 // 4. Delete Bucket Event 2612 events[0] = "put" 2613 deletEventResponse, deventError := DeleteBucketEvent( 2614 "testputobjectslegalholdstatus", // bucket name 2615 "arn:minio:sqs::_:postgresql", // arn 2616 events, // events 2617 "", // prefix 2618 "", // suffix 2619 ) 2620 assert.Nil(deventError) 2621 if deventError != nil { 2622 log.Println(deventError) 2623 return 2624 } 2625 efinalResponseEvent := inspectHTTPResponse(deletEventResponse) 2626 if deletEventResponse != nil { 2627 assert.Equal( 2628 204, 2629 deletEventResponse.StatusCode, 2630 efinalResponseEvent, 2631 ) 2632 } 2633 } 2634 2635 func SetMultiBucketReplication(accessKey, secretKey, targetURL, region, originBucket, destinationBucket, syncMode string, bandwidth, healthCheckPeriod int, prefix, tags string, replicateDeleteMarkers, replicateDeletes bool, priority int, storageClass string, replicateMetadata bool) (*http.Response, error) { 2636 /* 2637 Helper function 2638 URL: /buckets-replication 2639 HTTP Verb: POST 2640 Body: 2641 { 2642 "accessKey":"Q3AM3UQ867SPQQA43P2F", 2643 "secretKey":"zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG", 2644 "targetURL":"https://play.min.io", 2645 "region":"", 2646 "bucketsRelation":[ 2647 { 2648 "originBucket":"test", 2649 "destinationBucket":"versioningenabled" 2650 } 2651 ], 2652 "syncMode":"async", 2653 "bandwidth":107374182400, 2654 "healthCheckPeriod":60, 2655 "prefix":"", 2656 "tags":"", 2657 "replicateDeleteMarkers":true, 2658 "replicateDeletes":true, 2659 "priority":1, 2660 "storageClass":"", 2661 "replicateMetadata":true 2662 } 2663 */ 2664 bucketsRelationArray := make([]map[string]interface{}, 1) 2665 bucketsRelationIndex0 := map[string]interface{}{ 2666 "originBucket": originBucket, 2667 "destinationBucket": destinationBucket, 2668 } 2669 bucketsRelationArray[0] = bucketsRelationIndex0 2670 requestDataAdd := map[string]interface{}{ 2671 "accessKey": accessKey, 2672 "secretKey": secretKey, 2673 "targetURL": targetURL, 2674 "region": region, 2675 "bucketsRelation": bucketsRelationArray, 2676 "syncMode": syncMode, 2677 "bandwidth": bandwidth, 2678 "healthCheckPeriod": healthCheckPeriod, 2679 "prefix": prefix, 2680 "tags": tags, 2681 "replicateDeleteMarkers": replicateDeleteMarkers, 2682 "replicateDeletes": replicateDeletes, 2683 "priority": priority, 2684 "storageClass": storageClass, 2685 "replicateMetadata": replicateMetadata, 2686 } 2687 requestDataJSON, _ := json.Marshal(requestDataAdd) 2688 requestDataBody := bytes.NewReader(requestDataJSON) 2689 request, err := http.NewRequest( 2690 "POST", 2691 "http://localhost:9090/api/v1/buckets-replication", 2692 requestDataBody, 2693 ) 2694 if err != nil { 2695 log.Println(err) 2696 } 2697 request.Header.Add("Cookie", fmt.Sprintf("token=%s", token)) 2698 request.Header.Add("Content-Type", "application/json") 2699 client := &http.Client{ 2700 Timeout: 2 * time.Second, 2701 } 2702 response, err := client.Do(request) 2703 return response, err 2704 } 2705 2706 func GetBucketReplication(bucketName string) (*http.Response, error) { 2707 /* 2708 URL: /buckets/{bucket_name}/replication 2709 HTTP Verb: GET 2710 */ 2711 request, err := http.NewRequest("GET", 2712 "http://localhost:9090/api/v1/buckets/"+bucketName+"/replication", 2713 nil) 2714 if err != nil { 2715 log.Println(err) 2716 } 2717 request.Header.Add("Cookie", fmt.Sprintf("token=%s", token)) 2718 request.Header.Add("Content-Type", "application/json") 2719 client := &http.Client{ 2720 Timeout: 2 * time.Second, 2721 } 2722 response, err := client.Do(request) 2723 return response, err 2724 } 2725 2726 func DeletesAllReplicationRulesOnABucket(bucketName string) (*http.Response, error) { 2727 /* 2728 Helper function to delete all replication rules in a bucket 2729 URL: /buckets/{bucket_name}/delete-all-replication-rules 2730 HTTP Verb: DELETE 2731 */ 2732 request, err := http.NewRequest( 2733 "DELETE", 2734 "http://localhost:9090/api/v1/buckets/"+bucketName+"/delete-all-replication-rules", 2735 nil, 2736 ) 2737 if err != nil { 2738 log.Println(err) 2739 } 2740 request.Header.Add("Cookie", fmt.Sprintf("token=%s", token)) 2741 request.Header.Add("Content-Type", "application/json") 2742 client := &http.Client{ 2743 Timeout: 2 * time.Second, 2744 } 2745 response, err := client.Do(request) 2746 return response, err 2747 } 2748 2749 func DeleteMultipleReplicationRules(bucketName string, rules []string) (*http.Response, error) { 2750 /* 2751 Helper function to delete multiple replication rules in a bucket 2752 URL: /buckets/{bucket_name}/delete-multiple-replication-rules 2753 HTTP Verb: DELETE 2754 */ 2755 body := map[string]interface{}{ 2756 "rules": rules, 2757 } 2758 requestDataJSON, _ := json.Marshal(body) 2759 requestDataBody := bytes.NewReader(requestDataJSON) 2760 request, err := http.NewRequest( 2761 "DELETE", 2762 "http://localhost:9090/api/v1/buckets/"+bucketName+"/delete-selected-replication-rules", 2763 requestDataBody, 2764 ) 2765 if err != nil { 2766 log.Println(err) 2767 } 2768 request.Header.Add("Cookie", fmt.Sprintf("token=%s", token)) 2769 request.Header.Add("Content-Type", "application/json") 2770 client := &http.Client{ 2771 Timeout: 2 * time.Second, 2772 } 2773 response, err := client.Do(request) 2774 return response, err 2775 } 2776 2777 func DeleteBucketReplicationRule(bucketName, ruleID string) (*http.Response, error) { 2778 /* 2779 Helper function to delete a bucket's replication rule 2780 URL: /buckets/{bucket_name}/replication/{rule_id} 2781 HTTP Verb: DELETE 2782 */ 2783 request, err := http.NewRequest( 2784 "DELETE", 2785 "http://localhost:9090/api/v1/buckets/"+bucketName+"/replication/"+ruleID, 2786 nil, 2787 ) 2788 if err != nil { 2789 log.Println(err) 2790 } 2791 request.Header.Add("Cookie", fmt.Sprintf("token=%s", token)) 2792 request.Header.Add("Content-Type", "application/json") 2793 client := &http.Client{ 2794 Timeout: 2 * time.Second, 2795 } 2796 response, err := client.Do(request) 2797 return response, err 2798 } 2799 2800 func TestReplication(t *testing.T) { 2801 // Vars 2802 assert := assert.New(t) 2803 originBucket := "testputobjectslegalholdstatus" 2804 destinationBuckets := []string{"testgetbucketquota", "testputbucketquota", "testlistbucketevents"} // an array of strings to iterate over 2805 2806 // 1. Set replication rules with DIFFERENT PRIORITY <------- NOT SAME BUT DIFFERENT! 1, 2, etc. 2807 for index, destinationBucket := range destinationBuckets { 2808 response, err := SetMultiBucketReplication( 2809 "minioadmin", // accessKey string 2810 "minioadmin", // secretKey string 2811 "http://localhost:9000/", // targetURL string 2812 "", // region string 2813 originBucket, // originBucket string 2814 destinationBucket, // destinationBucket string 2815 "async", // syncMode string 2816 107374182400, // bandwidth int 2817 60, // healthCheckPeriod int 2818 "", // prefix string 2819 "", // tags string 2820 true, // replicateDeleteMarkers bool 2821 true, // replicateDeletes bool 2822 index+1, // priority int 2823 "", // storageClass string 2824 true, // replicateMetadata bool 2825 ) 2826 assert.Nil(err) 2827 if err != nil { 2828 log.Println(err) 2829 return 2830 } 2831 finalResponse := inspectHTTPResponse(response) 2832 if response != nil { 2833 assert.Equal(200, response.StatusCode, finalResponse) 2834 } 2835 2836 } 2837 2838 // 2. Get replication, at this point four rules are expected 2839 response, err := GetBucketReplication(originBucket) 2840 assert.Nil(err) 2841 if err != nil { 2842 log.Println(err) 2843 return 2844 } 2845 if response != nil { 2846 assert.Equal(200, response.StatusCode, "error invalid status") 2847 } 2848 2849 // 3. Get rule ID and status from response's body 2850 bodyBytes, _ := io.ReadAll(response.Body) 2851 structBucketRepl := models.BucketReplicationResponse{} 2852 err = json.Unmarshal(bodyBytes, &structBucketRepl) 2853 if err != nil { 2854 log.Println(err) 2855 assert.Nil(err) 2856 } 2857 2858 assert.Greater(len(structBucketRepl.Rules), 0, "Number of expected rules is 0") 2859 if len(structBucketRepl.Rules) == 0 || len(structBucketRepl.Rules) < 3 { 2860 return 2861 } 2862 // 4. Verify rules are enabled 2863 for index := 0; index < 3; index++ { 2864 Status := structBucketRepl.Rules[index].Status 2865 assert.Equal(Status, "Enabled") 2866 } 2867 2868 // 5. Delete 3rd and 4th rules with endpoint for multiple rules: 2869 // /buckets/{bucket_name}/replication/{rule_id} 2870 ruleIDs := []string{structBucketRepl.Rules[2].ID} // To delete 3rd rule with the multi delete function 2871 response, err = DeleteMultipleReplicationRules( 2872 originBucket, 2873 ruleIDs, 2874 ) 2875 assert.Nil(err) 2876 if err != nil { 2877 log.Println(err) 2878 return 2879 } 2880 finalResponse := inspectHTTPResponse(response) 2881 if response != nil { 2882 assert.Equal(204, response.StatusCode, finalResponse) 2883 } 2884 2885 // 6. Delete 2nd rule only with dedicated end point for single rules: 2886 // /buckets/{bucket_name}/replication/{rule_id} 2887 ruleID := structBucketRepl.Rules[1].ID // To delete 2nd rule in a single way 2888 response, err = DeleteBucketReplicationRule( 2889 originBucket, 2890 ruleID, 2891 ) 2892 assert.Nil(err) 2893 if err != nil { 2894 log.Println(err) 2895 return 2896 } 2897 finalResponse = inspectHTTPResponse(response) 2898 if response != nil { 2899 // https://github.com/minio/minio/pull/14972 2900 // Disallow deletion of arn when active replication config 2901 // 204 is no longer expected but 500 2902 assert.Equal(500, response.StatusCode, finalResponse) 2903 } 2904 2905 // 7. Delete remaining Bucket Replication Rule with generic end point: 2906 // /buckets/{bucket_name}/delete-all-replication-rules 2907 response, err = DeletesAllReplicationRulesOnABucket( 2908 originBucket, 2909 ) 2910 assert.Nil(err) 2911 if err != nil { 2912 log.Println(err) 2913 return 2914 } 2915 finalResponse = inspectHTTPResponse(response) 2916 if response != nil { 2917 assert.Equal(204, response.StatusCode, finalResponse) 2918 } 2919 2920 // 8. Get replication, at this point zero rules are expected 2921 response, err = GetBucketReplication(originBucket) 2922 assert.Nil(err) 2923 if err != nil { 2924 log.Println(err) 2925 return 2926 } 2927 if response != nil { 2928 assert.Equal(200, response.StatusCode, "error invalid status") 2929 } 2930 2931 // 9. Get rule ID and status from response's body 2932 bodyBytes, _ = io.ReadAll(response.Body) 2933 structBucketRepl = models.BucketReplicationResponse{} 2934 err = json.Unmarshal(bodyBytes, &structBucketRepl) 2935 if err != nil { 2936 log.Println(err) 2937 assert.Nil(err) 2938 } 2939 expected := 0 2940 actual := len(structBucketRepl.Rules) 2941 assert.Equal(expected, actual, "Delete failed") 2942 } 2943 2944 func GetBucketVersioning(bucketName string) (*http.Response, error) { 2945 /* 2946 Helper function to get bucket's versioning 2947 */ 2948 endPoint := "versioning" 2949 return BaseGetFunction(bucketName, endPoint) 2950 } 2951 2952 func ReturnsTheStatusOfObjectLockingSupportOnTheBucket(bucketName string) (*http.Response, error) { 2953 /* 2954 Helper function to test end point below: 2955 URL: /buckets/{bucket_name}/object-locking: 2956 HTTP Verb: GET 2957 */ 2958 endPoint := "object-locking" 2959 return BaseGetFunction(bucketName, endPoint) 2960 } 2961 2962 func BaseGetFunction(bucketName, endPoint string) (*http.Response, error) { 2963 request, err := http.NewRequest( 2964 "GET", 2965 "http://localhost:9090/api/v1/buckets/"+bucketName+"/"+endPoint, nil) 2966 if err != nil { 2967 log.Println(err) 2968 } 2969 request.Header.Add("Cookie", fmt.Sprintf("token=%s", token)) 2970 request.Header.Add("Content-Type", "application/json") 2971 client := &http.Client{ 2972 Timeout: 2 * time.Second, 2973 } 2974 response, err := client.Do(request) 2975 return response, err 2976 } 2977 2978 func TestReturnsTheStatusOfObjectLockingSupportOnTheBucket(t *testing.T) { 2979 // Test for end point: /buckets/{bucket_name}/object-locking 2980 2981 // Vars 2982 assert := assert.New(t) 2983 bucketName := "testputobjectslegalholdstatus" 2984 2985 // 1. Get the status 2986 response, err := ReturnsTheStatusOfObjectLockingSupportOnTheBucket( 2987 bucketName, 2988 ) 2989 assert.Nil(err) 2990 if err != nil { 2991 log.Println(err) 2992 return 2993 } 2994 if response != nil { 2995 assert.Equal(200, response.StatusCode, "error invalid status") 2996 } 2997 2998 // 2. Verify the status to be enabled for this bucket 2999 bodyBytes, _ := io.ReadAll(response.Body) 3000 structBucketLocking := models.BucketObLockingResponse{} 3001 err = json.Unmarshal(bodyBytes, &structBucketLocking) 3002 if err != nil { 3003 log.Println(err) 3004 assert.Nil(err) 3005 } 3006 assert.Equal( 3007 structBucketLocking.ObjectLockingEnabled, 3008 true, 3009 structBucketLocking, 3010 ) 3011 } 3012 3013 func SetBucketVersioning(bucketName string, versioning map[string]interface{}, endpoint, useToken *string) (*http.Response, error) { 3014 /* 3015 Helper function to set Bucket Versioning 3016 */ 3017 requestDataAdd := map[string]interface{}{ 3018 "versioning": versioning, 3019 } 3020 requestDataJSON, _ := json.Marshal(requestDataAdd) 3021 requestDataBody := bytes.NewReader(requestDataJSON) 3022 endpointURL := fmt.Sprintf("http://localhost:9090/api/v1/buckets/%s/versioning", bucketName) 3023 if endpoint != nil { 3024 endpointURL = fmt.Sprintf("%s/api/v1/buckets/%s/versioning", *endpoint, bucketName) 3025 } 3026 request, err := http.NewRequest("PUT", 3027 endpointURL, 3028 requestDataBody) 3029 if err != nil { 3030 log.Println(err) 3031 } 3032 if useToken != nil { 3033 request.Header.Add("Cookie", fmt.Sprintf("token=%s", *useToken)) 3034 } else { 3035 request.Header.Add("Cookie", fmt.Sprintf("token=%s", token)) 3036 } 3037 request.Header.Add("Content-Type", "application/json") 3038 client := &http.Client{ 3039 Timeout: 2 * time.Second, 3040 } 3041 response, err := client.Do(request) 3042 return response, err 3043 } 3044 3045 func TestSetBucketVersioning(t *testing.T) { 3046 // Variables 3047 assert := assert.New(t) 3048 bucket := "test-set-bucket-versioning" 3049 locking := false 3050 versioning := map[string]interface{}{"enabled": true} 3051 3052 // 1. Create bucket with versioning as true and locking as false 3053 if !setupBucket(bucket, locking, versioning, nil, nil, assert, 200) { 3054 return 3055 } 3056 3057 // 2. Set versioning as False i.e Suspend versioning 3058 response, err := SetBucketVersioning(bucket, map[string]interface{}{"enabled": false}, nil, nil) 3059 assert.Nil(err) 3060 if err != nil { 3061 log.Println(err) 3062 assert.Fail("Error setting the bucket versioning") 3063 return 3064 } 3065 if response != nil { 3066 assert.Equal(201, response.StatusCode, inspectHTTPResponse(response)) 3067 } 3068 3069 // 3. Read the HTTP Response and make sure is disabled. 3070 getVersioningResult, getVersioningError := GetBucketVersioning(bucket) 3071 assert.Nil(getVersioningError) 3072 if getVersioningError != nil { 3073 log.Println(getVersioningError) 3074 return 3075 } 3076 if getVersioningResult != nil { 3077 assert.Equal( 3078 200, getVersioningResult.StatusCode, "Status Code is incorrect") 3079 } 3080 bodyBytes, _ := io.ReadAll(getVersioningResult.Body) 3081 result := models.BucketVersioningResponse{ 3082 ExcludeFolders: false, 3083 ExcludedPrefixes: nil, 3084 MFADelete: "", 3085 Status: "", 3086 } 3087 err = json.Unmarshal(bodyBytes, &result) 3088 if err != nil { 3089 log.Println(err) 3090 assert.Nil(err) 3091 } 3092 assert.Equal("Suspended", result.Status, result) 3093 } 3094 3095 func EnableBucketEncryption(bucketName, encType, kmsKeyID string) (*http.Response, error) { 3096 // Helper function to enable bucket encryption 3097 // HTTP Verb: POST 3098 // URL: /buckets/{bucket_name}/encryption/enable 3099 // Body: 3100 // { 3101 // "encType":"sse-s3", 3102 // "kmsKeyID":"" 3103 // } 3104 requestDataAdd := map[string]interface{}{ 3105 "encType": encType, 3106 "kmsKeyID": kmsKeyID, 3107 } 3108 requestDataJSON, _ := json.Marshal(requestDataAdd) 3109 requestDataBody := bytes.NewReader(requestDataJSON) 3110 request, err := http.NewRequest( 3111 "POST", "http://localhost:9090/api/v1/buckets/"+bucketName+"/encryption/enable", requestDataBody) 3112 if err != nil { 3113 log.Println(err) 3114 } 3115 request.Header.Add("Cookie", fmt.Sprintf("token=%s", token)) 3116 request.Header.Add("Content-Type", "application/json") 3117 3118 // Performing the call 3119 client := &http.Client{ 3120 Timeout: 2 * time.Second, 3121 } 3122 response, err := client.Do(request) 3123 return response, err 3124 } 3125 3126 func TestEnableBucketEncryption(t *testing.T) { 3127 // Variables 3128 assert := assert.New(t) 3129 bucketName := "test-enable-bucket-encryption" 3130 locking := false 3131 encType := "sse-s3" 3132 kmsKeyID := "" 3133 3134 // 1. Add bucket 3135 if !setupBucket(bucketName, locking, nil, nil, nil, assert, 200) { 3136 return 3137 } 3138 3139 // 2. Enable Bucket's Encryption 3140 resp, err := EnableBucketEncryption(bucketName, encType, kmsKeyID) 3141 assert.Nil(err) 3142 if err != nil { 3143 log.Println(err) 3144 return 3145 } 3146 if resp != nil { 3147 assert.Equal( 3148 200, resp.StatusCode, "Status Code is incorrect") 3149 } 3150 3151 // 3. Get Bucket Encryption Information to verify it got encrypted. 3152 resp, err = GetBucketEncryptionInformation(bucketName) 3153 assert.Nil(err) 3154 if err != nil { 3155 log.Println(err) 3156 return 3157 } 3158 if resp != nil { 3159 assert.Equal( 3160 200, resp.StatusCode, "Status Code is incorrect") 3161 } 3162 bodyBytes, _ := io.ReadAll(resp.Body) 3163 result := models.BucketEncryptionInfo{} 3164 err = json.Unmarshal(bodyBytes, &result) 3165 if err != nil { 3166 log.Println(err) 3167 assert.Nil(err) 3168 } 3169 assert.Equal("AES256", result.Algorithm, result) 3170 3171 // 4. Disable Bucket's Encryption 3172 resp, err = DisableBucketEncryption(bucketName) 3173 assert.Nil(err) 3174 if err != nil { 3175 log.Println(err) 3176 return 3177 } 3178 if resp != nil { 3179 assert.Equal( 3180 200, resp.StatusCode, "Status Code is incorrect") 3181 } 3182 3183 // 5. Verify encryption got disabled. 3184 resp, err = GetBucketEncryptionInformation(bucketName) 3185 assert.Nil(err) 3186 if err != nil { 3187 log.Println(err) 3188 return 3189 } 3190 if resp != nil { 3191 assert.Equal( 3192 404, resp.StatusCode, "Status Code is incorrect") 3193 } 3194 bodyBytes, _ = io.ReadAll(resp.Body) 3195 result2 := models.APIError{} 3196 err = json.Unmarshal(bodyBytes, &result2) 3197 if err != nil { 3198 log.Println(err) 3199 assert.Nil(err) 3200 } 3201 dereferencedPointerDetailedMessage := result2.DetailedMessage 3202 assert.Equal("error server side encryption configuration not found", dereferencedPointerDetailedMessage, dereferencedPointerDetailedMessage) 3203 } 3204 3205 func GetBucketEncryptionInformation(bucketName string) (*http.Response, error) { 3206 /* 3207 Helper function to get bucket encryption information 3208 HTTP Verb: GET 3209 URL: api/v1/buckets/<bucket-name>/encryption/info 3210 Response: {"algorithm":"AES256"} 3211 */ 3212 request, err := http.NewRequest( 3213 "GET", "http://localhost:9090/api/v1/buckets/"+bucketName+"/encryption/info", nil) 3214 if err != nil { 3215 log.Println(err) 3216 } 3217 request.Header.Add("Cookie", fmt.Sprintf("token=%s", token)) 3218 request.Header.Add("Content-Type", "application/json") 3219 client := &http.Client{ 3220 Timeout: 2 * time.Second, 3221 } 3222 response, err := client.Do(request) 3223 return response, err 3224 } 3225 3226 func DisableBucketEncryption(bucketName string) (*http.Response, error) { 3227 /* 3228 Helper function to disable bucket's encryption 3229 HTTP Verb: POST 3230 URL: /buckets/{bucket_name}/encryption/disable 3231 */ 3232 request, err := http.NewRequest( 3233 "POST", 3234 "http://localhost:9090/api/v1/buckets/"+bucketName+"/encryption/disable", 3235 nil, 3236 ) 3237 if err != nil { 3238 log.Println(err) 3239 } 3240 request.Header.Add("Cookie", fmt.Sprintf("token=%s", token)) 3241 request.Header.Add("Content-Type", "application/json") 3242 client := &http.Client{ 3243 Timeout: 2 * time.Second, 3244 } 3245 response, err := client.Do(request) 3246 return response, err 3247 } 3248 3249 func UpdateLifecycleRule(bucketName, ltype string, disable bool, prefix, tags string, expiredObjectDeleteMarker bool, expiryDays, noncurrentversionExpirationDays int64, lifecycleID string) (*http.Response, error) { 3250 // Helper function to update lifecycle rule 3251 // HTTP Verb: PUT 3252 // URL: /buckets/{bucket_name}/lifecycle/{lifecycle_id} 3253 // Body Example: 3254 // { 3255 // "type":"expiry", 3256 // "disable":false, 3257 // "prefix":"", 3258 // "tags":"", 3259 // "expired_object_delete_marker":false, 3260 // "expiry_days":2, 3261 // "noncurrentversion_expiration_days":0 3262 // } 3263 3264 requestDataAdd := map[string]interface{}{ 3265 "type": ltype, 3266 "disable": disable, 3267 "prefix": prefix, 3268 "tags": tags, 3269 "expired_object_delete_marker": expiredObjectDeleteMarker, 3270 "expiry_days": expiryDays, 3271 "noncurrentversion_expiration_days": noncurrentversionExpirationDays, 3272 } 3273 requestDataJSON, _ := json.Marshal(requestDataAdd) 3274 requestDataBody := bytes.NewReader(requestDataJSON) 3275 request, err := http.NewRequest("PUT", 3276 "http://localhost:9090/api/v1/buckets/"+bucketName+"/lifecycle/"+lifecycleID, 3277 requestDataBody) 3278 if err != nil { 3279 log.Println(err) 3280 } 3281 request.Header.Add("Cookie", fmt.Sprintf("token=%s", token)) 3282 request.Header.Add("Content-Type", "application/json") 3283 client := &http.Client{ 3284 Timeout: 2 * time.Second, 3285 } 3286 response, err := client.Do(request) 3287 return response, err 3288 } 3289 3290 func GetBucketLifeCycle(bucketName string) (*http.Response, error) { 3291 // Get Bucket Lifecycle 3292 // HTTP Verb: GET 3293 // URL: /buckets/{bucket_name}/lifecycle 3294 // Response Example: 3295 // { 3296 // "lifecycle": [ 3297 // { 3298 // "expiration": { 3299 // "date": "0001-01-01T00:00:00Z", 3300 // "days": 1 3301 // }, 3302 // "id": "c8nmpte49b3m6uu3pac0", 3303 // "status": "Enabled", 3304 // "tags": null, 3305 // "transition": { 3306 // "date": "0001-01-01T00:00:00Z" 3307 // } 3308 // } 3309 // ] 3310 // } 3311 request, err := http.NewRequest( 3312 "GET", "http://localhost:9090/api/v1/buckets/"+bucketName+"/lifecycle", nil) 3313 if err != nil { 3314 log.Println(err) 3315 } 3316 request.Header.Add("Cookie", fmt.Sprintf("token=%s", token)) 3317 request.Header.Add("Content-Type", "application/json") 3318 client := &http.Client{ 3319 Timeout: 2 * time.Second, 3320 } 3321 response, err := client.Do(request) 3322 return response, err 3323 } 3324 3325 func AddBucketLifecycle(bucketName, ltype, prefix, tags string, expiredObjectDeleteMarker bool, expiryDays, noncurrentversionExpirationDays int64) (*http.Response, error) { 3326 // Helper function to add bucket lifecycle 3327 // URL: /buckets/{bucket_name}/lifecycle 3328 // HTTP Verb: POST 3329 // Body Example: 3330 // { 3331 // "type":"expiry", 3332 // "prefix":"", 3333 // "tags":"", 3334 // "expired_object_delete_marker":false, 3335 // "expiry_days":1, 3336 // "noncurrentversion_expiration_days":null 3337 // } 3338 // Needed Parameters for API Call 3339 requestDataAdd := map[string]interface{}{ 3340 "type": ltype, 3341 "prefix": prefix, 3342 "tags": tags, 3343 "expired_object_delete_marker": expiredObjectDeleteMarker, 3344 "expiry_days": expiryDays, 3345 "noncurrentversion_expiration_days": noncurrentversionExpirationDays, 3346 } 3347 3348 // Creating the Call by adding the URL and Headers 3349 requestDataJSON, _ := json.Marshal(requestDataAdd) 3350 requestDataBody := bytes.NewReader(requestDataJSON) 3351 request, err := http.NewRequest( 3352 "POST", 3353 "http://localhost:9090/api/v1/buckets/"+bucketName+"/lifecycle", 3354 requestDataBody, 3355 ) 3356 if err != nil { 3357 log.Println(err) 3358 } 3359 request.Header.Add("Cookie", fmt.Sprintf("token=%s", token)) 3360 request.Header.Add("Content-Type", "application/json") 3361 3362 // Performing the call 3363 client := &http.Client{ 3364 Timeout: 2 * time.Second, 3365 } 3366 response, err := client.Do(request) 3367 return response, err 3368 } 3369 3370 func DeleteLifecycleRule(bucketName, lifecycleID string) (*http.Response, error) { 3371 // Helper function to delete lifecycle rule 3372 // HTTP Verb: DELETE 3373 // URL: /buckets/{bucket_name}/lifecycle/{lifecycle_id} 3374 request, err := http.NewRequest( 3375 "DELETE", "http://localhost:9090/api/v1/buckets/"+bucketName+"/lifecycle/"+lifecycleID, nil) 3376 if err != nil { 3377 log.Println(err) 3378 } 3379 request.Header.Add("Cookie", fmt.Sprintf("token=%s", token)) 3380 request.Header.Add("Content-Type", "application/json") 3381 client := &http.Client{ 3382 Timeout: 2 * time.Second, 3383 } 3384 response, err := client.Do(request) 3385 return response, err 3386 } 3387 3388 func TestBucketLifeCycle(t *testing.T) { 3389 // Variables 3390 assert := assert.New(t) 3391 bucketName := "test-bucket-life-cycle" 3392 locking := false 3393 ltype := "expiry" 3394 prefix := "" 3395 tags := "" 3396 var expiryDays int64 = 1 3397 var expiryDays2 int64 = 2 3398 disable := false 3399 expiredObjectDeleteMarker := false 3400 var noncurrentversionExpirationDays int64 3401 3402 // 1. Add bucket 3403 if !setupBucket(bucketName, locking, nil, nil, nil, assert, 200) { 3404 return 3405 } 3406 3407 // 2. Add Bucket Lifecycle 3408 resp, err := AddBucketLifecycle( 3409 bucketName, 3410 ltype, 3411 prefix, 3412 tags, 3413 expiredObjectDeleteMarker, 3414 expiryDays, 3415 noncurrentversionExpirationDays, 3416 ) 3417 assert.Nil(err) 3418 if err != nil { 3419 log.Println(err) 3420 return 3421 } 3422 if resp != nil { 3423 assert.Equal( 3424 201, resp.StatusCode, "Status Code is incorrect") 3425 } 3426 3427 // 3. Get Bucket LifeCycle 3428 resp, err = GetBucketLifeCycle(bucketName) 3429 assert.Nil(err) 3430 if err != nil { 3431 log.Println(err) 3432 return 3433 } 3434 if resp != nil { 3435 assert.Equal( 3436 200, resp.StatusCode, "Status Code is incorrect") 3437 } 3438 bodyBytes, _ := io.ReadAll(resp.Body) 3439 result := models.BucketLifecycleResponse{} 3440 err = json.Unmarshal(bodyBytes, &result) 3441 if err != nil { 3442 log.Println(err) 3443 assert.Nil(err) 3444 } 3445 Status := &result.Lifecycle[0].Status 3446 Days := &result.Lifecycle[0].Expiration.Days 3447 lifecycleID := &result.Lifecycle[0].ID 3448 assert.Equal(expiryDays, *Days, *Days) // Checking it is one day expiration 3449 assert.Equal("Enabled", *Status, *Status) // Checking it's enabled 3450 3451 // 4. Update from 1 day expiration to 2 days expiration 3452 resp, err = UpdateLifecycleRule( 3453 bucketName, 3454 ltype, 3455 disable, 3456 prefix, 3457 tags, 3458 expiredObjectDeleteMarker, 3459 expiryDays2, 3460 noncurrentversionExpirationDays, 3461 *lifecycleID, 3462 ) 3463 assert.Nil(err) 3464 if err != nil { 3465 log.Println(err) 3466 return 3467 } 3468 if resp != nil { 3469 assert.Equal( 3470 200, resp.StatusCode, "Status Code is incorrect") 3471 } 3472 3473 // 5. Verify 2 expiration days got updated 3474 resp, err = GetBucketLifeCycle(bucketName) 3475 assert.Nil(err) 3476 if err != nil { 3477 log.Println(err) 3478 return 3479 } 3480 if resp != nil { 3481 assert.Equal( 3482 200, resp.StatusCode, "Status Code is incorrect") 3483 } 3484 bodyBytes, _ = io.ReadAll(resp.Body) 3485 result = models.BucketLifecycleResponse{} 3486 err = json.Unmarshal(bodyBytes, &result) 3487 if err != nil { 3488 log.Println(err) 3489 assert.Nil(err) 3490 } 3491 Days = &result.Lifecycle[0].Expiration.Days 3492 assert.Equal(expiryDays2, *Days, *Days) // Checking it is two days expiration 3493 3494 // 6. Delete Bucket Lifecycle 3495 resp, err = DeleteLifecycleRule(bucketName, *lifecycleID) 3496 assert.Nil(err) 3497 if err != nil { 3498 log.Println(err) 3499 return 3500 } 3501 if resp != nil { 3502 assert.Equal( 3503 204, resp.StatusCode, "Status Code is incorrect") 3504 } 3505 3506 // 6. Verify bucket lifecycle got deleted 3507 resp, err = GetBucketLifeCycle(bucketName) 3508 assert.Nil(err) 3509 if err != nil { 3510 log.Println(err) 3511 return 3512 } 3513 if resp != nil { 3514 assert.Equal( 3515 404, resp.StatusCode, "Status Code is incorrect") 3516 } 3517 } 3518 3519 func SetAccessRuleWithBucket(bucketName, prefix, access string) (*http.Response, error) { 3520 /* 3521 Helper function to Set Access Rule within Bucket 3522 HTTP Verb: PUT 3523 URL: /bucket/{bucket}/access-rules 3524 Data Example: 3525 { 3526 "prefix":"prefix", 3527 "access":"readonly" 3528 } 3529 */ 3530 requestDataAdd := map[string]interface{}{ 3531 "prefix": prefix, 3532 "access": access, 3533 } 3534 requestDataJSON, _ := json.Marshal(requestDataAdd) 3535 requestDataBody := bytes.NewReader(requestDataJSON) 3536 request, err := http.NewRequest( 3537 "PUT", 3538 "http://localhost:9090/api/v1/bucket/"+bucketName+"/access-rules", 3539 requestDataBody, 3540 ) 3541 if err != nil { 3542 log.Println(err) 3543 } 3544 request.Header.Add("Cookie", fmt.Sprintf("token=%s", token)) 3545 request.Header.Add("Content-Type", "application/json") 3546 client := &http.Client{ 3547 Timeout: 2 * time.Second, 3548 } 3549 response, err := client.Do(request) 3550 return response, err 3551 } 3552 3553 func ListAccessRulesWithBucket(bucketName string) (*http.Response, error) { 3554 /* 3555 Helper function to List Access Rules Within Bucket 3556 HTTP Verb: GET 3557 URL: /bucket/{bucket}/access-rules 3558 */ 3559 request, err := http.NewRequest( 3560 "GET", 3561 "http://localhost:9090/api/v1/bucket/"+bucketName+"/access-rules", nil) 3562 if err != nil { 3563 log.Println(err) 3564 } 3565 request.Header.Add("Cookie", fmt.Sprintf("token=%s", token)) 3566 request.Header.Add("Content-Type", "application/json") 3567 client := &http.Client{ 3568 Timeout: 2 * time.Second, 3569 } 3570 response, err := client.Do(request) 3571 return response, err 3572 } 3573 3574 func DeleteAccessRuleWithBucket(bucketName, prefix string) (*http.Response, error) { 3575 /* 3576 Helper function to Delete Access Rule With Bucket 3577 HTTP Verb: DELETE 3578 URL: /bucket/{bucket}/access-rules 3579 Data Example: {"prefix":"prefix"} 3580 */ 3581 requestDataAdd := map[string]interface{}{ 3582 "prefix": prefix, 3583 } 3584 requestDataJSON, _ := json.Marshal(requestDataAdd) 3585 requestDataBody := bytes.NewReader(requestDataJSON) 3586 request, err := http.NewRequest( 3587 "DELETE", 3588 "http://localhost:9090/api/v1/bucket/"+bucketName+"/access-rules", 3589 requestDataBody, 3590 ) 3591 if err != nil { 3592 log.Println(err) 3593 } 3594 request.Header.Add("Cookie", fmt.Sprintf("token=%s", token)) 3595 request.Header.Add("Content-Type", "application/json") 3596 client := &http.Client{ 3597 Timeout: 2 * time.Second, 3598 } 3599 response, err := client.Do(request) 3600 return response, err 3601 } 3602 3603 func TestAccessRule(t *testing.T) { 3604 // Variables 3605 assert := assert.New(t) 3606 bucketName := "test-access-rule-bucket" 3607 locking := false 3608 prefix := "prefix" 3609 access := "readonly" 3610 3611 // 1. Add bucket 3612 if !setupBucket(bucketName, locking, nil, nil, nil, assert, 200) { 3613 return 3614 } 3615 3616 // 2. Set Access Rule With Bucket 3617 resp, err := SetAccessRuleWithBucket( 3618 bucketName, 3619 prefix, 3620 access, 3621 ) 3622 assert.Nil(err) 3623 if err != nil { 3624 log.Println(err) 3625 return 3626 } 3627 if resp != nil { 3628 assert.Equal( 3629 200, resp.StatusCode, "Status Code is incorrect") 3630 } 3631 3632 // 3. List Access Rule 3633 resp, err = ListAccessRulesWithBucket(bucketName) 3634 assert.Nil(err) 3635 if err != nil { 3636 log.Println(err) 3637 return 3638 } 3639 if resp != nil { 3640 assert.Equal( 3641 200, resp.StatusCode, "Status Code is incorrect") 3642 } 3643 bodyBytes, _ := io.ReadAll(resp.Body) 3644 result := models.ListAccessRulesResponse{} 3645 err = json.Unmarshal(bodyBytes, &result) 3646 if err != nil { 3647 log.Println(err) 3648 assert.Nil(err) 3649 } 3650 Access := &result.AccessRules[0].Access 3651 Prefix := &result.AccessRules[0].Prefix 3652 assert.Equal("readonly", *Access, *Access) 3653 assert.Equal("prefix", *Prefix, *Prefix) 3654 3655 // 4. Delete Access Rule 3656 resp, err = DeleteAccessRuleWithBucket( 3657 bucketName, 3658 prefix, 3659 ) 3660 assert.Nil(err) 3661 if err != nil { 3662 log.Println(err) 3663 return 3664 } 3665 if resp != nil { 3666 assert.Equal( 3667 200, resp.StatusCode, "Status Code is incorrect") 3668 } 3669 3670 // 5. Verify access rule was deleted 3671 resp, err = ListAccessRulesWithBucket(bucketName) 3672 assert.Nil(err) 3673 if err != nil { 3674 log.Println(err) 3675 return 3676 } 3677 if resp != nil { 3678 assert.Equal( 3679 200, resp.StatusCode, "Status Code is incorrect") 3680 } 3681 bodyBytes, _ = io.ReadAll(resp.Body) 3682 result = models.ListAccessRulesResponse{} 3683 err = json.Unmarshal(bodyBytes, &result) 3684 if err != nil { 3685 log.Println(err) 3686 assert.Nil(err) 3687 } 3688 AccessRules := &result.AccessRules // The array has to be empty, no index accessible 3689 if len(*AccessRules) == 0 { 3690 fmt.Println("Cool, access rules are gone from this bucket") 3691 } else { 3692 assert.Fail("Access Rule not deleted") 3693 } 3694 } 3695 3696 func GetBucketRewind(bucketName, date string) (*http.Response, error) { 3697 /* 3698 Helper function to get objects in a bucket for a rewind date 3699 HTTP Verb: GET 3700 URL: /buckets/{bucket_name}/rewind/{date} 3701 */ 3702 request, err := http.NewRequest( 3703 "GET", 3704 "http://localhost:9090/api/v1/buckets/"+bucketName+"/rewind/"+date, 3705 nil, 3706 ) 3707 if err != nil { 3708 log.Println(err) 3709 } 3710 request.Header.Add("Cookie", fmt.Sprintf("token=%s", token)) 3711 request.Header.Add("Content-Type", "application/json") 3712 client := &http.Client{ 3713 Timeout: 2 * time.Second, 3714 } 3715 response, err := client.Do(request) 3716 return response, err 3717 } 3718 3719 func TestGetBucketRewind(t *testing.T) { 3720 // Variables 3721 assert := assert.New(t) 3722 bucketName := "test-get-bucket-rewind" 3723 date := "2006-01-02T15:04:05Z" 3724 3725 // Test 3726 resp, err := GetBucketRewind(bucketName, date) 3727 assert.Nil(err) 3728 if err != nil { 3729 log.Println(err) 3730 return 3731 } 3732 if resp != nil { 3733 assert.Equal( 3734 200, resp.StatusCode, inspectHTTPResponse(resp)) 3735 } 3736 } 3737 3738 func GetRemoteBucket() (*http.Response, error) { 3739 request, err := http.NewRequest( 3740 "GET", 3741 "http://localhost:9090/api/v1/remote-buckets", 3742 nil, 3743 ) 3744 if err != nil { 3745 log.Println(err) 3746 } 3747 request.Header.Add("Cookie", fmt.Sprintf("token=%s", token)) 3748 request.Header.Add("Content-Type", "application/json") 3749 client := &http.Client{ 3750 Timeout: 2 * time.Second, 3751 } 3752 response, err := client.Do(request) 3753 return response, err 3754 } 3755 3756 func GetRemoteBucketARN(sourceBucket string) (*http.Response, error) { 3757 request, err := http.NewRequest( 3758 "GET", 3759 fmt.Sprintf("http://localhost:9090/api/v1/remote-buckets/%s", sourceBucket), 3760 nil, 3761 ) 3762 if err != nil { 3763 log.Println(err) 3764 } 3765 request.Header.Add("Cookie", fmt.Sprintf("token=%s", token)) 3766 request.Header.Add("Content-Type", "application/json") 3767 client := &http.Client{ 3768 Timeout: 2 * time.Second, 3769 } 3770 response, err := client.Do(request) 3771 return response, err 3772 } 3773 3774 func AddRemoteBucket(accessKey, secretKey, targetURL, sourceBucket, targetBucket string) (*http.Response, error) { 3775 // Needed Parameters for API Call 3776 bucketsRelationArray := make([]map[string]interface{}, 1) 3777 bucketsRelationIndex0 := map[string]interface{}{ 3778 "originBucket": sourceBucket, 3779 "destinationBucket": targetBucket, 3780 } 3781 bucketsRelationArray[0] = bucketsRelationIndex0 3782 requestDataAdd := map[string]interface{}{ 3783 "accessKey": accessKey, 3784 "secretKey": secretKey, 3785 "targetURL": targetURL, 3786 "sourceBucket": sourceBucket, 3787 "targetBucket": targetBucket, 3788 "region": "", 3789 "bucketsRelation": bucketsRelationArray, 3790 "syncMode": "async", 3791 "bandwidth": 107374182400, 3792 "healthCheckPeriod": 60, 3793 "prefix": "", 3794 "tags": "", 3795 "replicateDeleteMarkers": true, 3796 "replicateDeletes": true, 3797 "priority": 1, 3798 "storageClass": "", 3799 "replicateMetadata": true, 3800 } 3801 3802 // Creating the Call by adding the URL and Headers 3803 requestDataJSON, _ := json.Marshal(requestDataAdd) 3804 requestDataBody := bytes.NewReader(requestDataJSON) 3805 request, err := http.NewRequest( 3806 "POST", 3807 "http://localhost:9090/api/v1/remote-buckets", 3808 requestDataBody, 3809 ) 3810 if err != nil { 3811 log.Println(err) 3812 } 3813 request.Header.Add("Cookie", fmt.Sprintf("token=%s", token)) 3814 request.Header.Add("Content-Type", "application/json") 3815 3816 // Performing the call 3817 client := &http.Client{ 3818 Timeout: 2 * time.Second, 3819 } 3820 response, err := client.Do(request) 3821 return response, err 3822 } 3823 3824 func DeleteRemoteBucket(sourceBucket string, arn string) (*http.Response, error) { 3825 // Needed Parameters for API Call 3826 request, err := http.NewRequest( 3827 "DELETE", 3828 fmt.Sprintf("http://localhost:9090/api/v1/remote-buckets/%s/%s", sourceBucket, arn), 3829 nil, 3830 ) 3831 if err != nil { 3832 log.Println(err) 3833 } 3834 request.Header.Add("Cookie", fmt.Sprintf("token=%s", token)) 3835 request.Header.Add("Content-Type", "application/json") 3836 3837 // Performing the call 3838 client := &http.Client{ 3839 Timeout: 2 * time.Second, 3840 } 3841 response, err := client.Do(request) 3842 return response, err 3843 } 3844 3845 func TestAddRemoteBucket(t *testing.T) { 3846 // Variables 3847 assert := assert.New(t) 3848 accessKey := "minioadmin" 3849 secretKey := "minioadmin" 3850 targetURL := "http://173.18.0.3:9001" 3851 sourceBucket := "source" 3852 targetBucket := "targetbucket" 3853 fmt.Println("targetBucket: ", targetBucket) 3854 3855 // 1. Create bucket 3856 if !setupBucket("source", true, map[string]interface{}{"enabled": true}, nil, nil, assert, 200) { 3857 return 3858 } 3859 // 1.1. Create target bucket 3860 targetEndpoint := "http://localhost:9092" 3861 targetToken := getTokenForEndpoint(targetEndpoint) 3862 if !setupBucketForEndpoint(targetBucket, true, map[string]interface{}{"enabled": true}, nil, nil, assert, 200, &targetEndpoint, &targetToken) { 3863 log.Println("bucket already exists") 3864 } 3865 _, err := SetBucketVersioning(targetBucket, map[string]interface{}{"enabled": false}, &targetURL, &targetToken) 3866 if err != nil { 3867 log.Println("bucket already has versioning") 3868 } 3869 3870 // 2. Add Remote Bucket 3871 resp, err := AddRemoteBucket( 3872 accessKey, 3873 secretKey, 3874 targetURL, 3875 sourceBucket, 3876 targetBucket, 3877 ) 3878 assert.Nil(err) 3879 if err != nil { 3880 log.Println(err) 3881 return 3882 } 3883 if resp != nil { 3884 assert.Equal( 3885 201, resp.StatusCode, inspectHTTPResponse(resp)) 3886 } 3887 3888 // 3. Verify Remote Bucket was created 3889 resp, err = GetRemoteBucket() 3890 assert.Nil(err) 3891 if err != nil { 3892 log.Println(err) 3893 return 3894 } 3895 finalResponse := inspectHTTPResponse(resp) 3896 if resp != nil { 3897 assert.Equal( 3898 200, resp.StatusCode, finalResponse) 3899 } 3900 fmt.Println("finalResponse: ", finalResponse) 3901 assert.Equal(strings.Contains(finalResponse, targetBucket), true) 3902 } 3903 3904 func TestDeleteRemoteBucket(t *testing.T) { 3905 // Variables 3906 assert := assert.New(t) 3907 accessKey := "minioadmin" 3908 secretKey := "minioadmin" 3909 targetURL := "http://173.18.0.3:9001" 3910 sourceBucket := "deletesource" 3911 targetBucket := "targetbucket2" 3912 fmt.Println("targetBucket: ", targetBucket) 3913 3914 // 1. Create bucket 3915 if !setupBucket("deletesource", true, map[string]interface{}{"enabled": true}, nil, nil, assert, 200) { 3916 return 3917 } 3918 // 1.1. Create target bucket 3919 targetEndpoint := "http://localhost:9092" 3920 targetToken := getTokenForEndpoint(targetEndpoint) 3921 if !setupBucketForEndpoint(targetBucket, true, map[string]interface{}{"enabled": true}, nil, nil, assert, 200, &targetEndpoint, &targetToken) { 3922 log.Println("bucket already exists") 3923 } 3924 _, err := SetBucketVersioning(targetBucket, map[string]interface{}{"enabled": false}, &targetURL, &targetToken) 3925 if err != nil { 3926 log.Println("bucket already has versioning") 3927 } 3928 3929 // 2. Add Remote Bucket 3930 resp, err := AddRemoteBucket( 3931 accessKey, 3932 secretKey, 3933 targetURL, 3934 sourceBucket, 3935 targetBucket, 3936 ) 3937 assert.Nil(err) 3938 if err != nil { 3939 log.Println(err) 3940 return 3941 } 3942 if resp != nil { 3943 assert.Equal( 3944 201, resp.StatusCode, inspectHTTPResponse(resp)) 3945 } 3946 3947 // 3. Get ARN 3948 resp, err = GetRemoteBucketARN(sourceBucket) 3949 assert.Nil(err) 3950 assert.NotNil(resp) 3951 assert.NotNil(resp.Body) 3952 bodyBytes, _ := io.ReadAll(resp.Body) 3953 remoteBucket := models.RemoteBucket{} 3954 err = json.Unmarshal(bodyBytes, &remoteBucket) 3955 assert.Nil(err) 3956 assert.Equal(200, resp.StatusCode, inspectHTTPResponse(resp)) 3957 3958 // 4. Delete Remote Bucket 3959 if remoteBucket.RemoteARN != nil { 3960 resp, err = DeleteRemoteBucket(sourceBucket, *remoteBucket.RemoteARN) 3961 assert.Nil(err) 3962 if err != nil { 3963 log.Println(err) 3964 return 3965 } 3966 finalResponse := inspectHTTPResponse(resp) 3967 if resp != nil { 3968 assert.Equal( 3969 204, resp.StatusCode, finalResponse) 3970 } 3971 } else { 3972 assert.Fail("No remote arn response") 3973 } 3974 }