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  }