diff --git a/commons/client.go b/commons/client.go index aaf6ed4..a435cf8 100644 --- a/commons/client.go +++ b/commons/client.go @@ -5,7 +5,6 @@ import ( "encoding/json" "fmt" "io" - "log" "net/http" "net/http/httptest" "net/url" @@ -113,7 +112,6 @@ func (c *Client) SendRequest(req *http.Request) ([]byte, error) { body, err := io.ReadAll(resp.Body) c.LastJSONResponse = string(body) - log.Printf("[DEBUG] Response: %s - URL: %s", c.LastJSONResponse, resp.Request.URL.String()) if resp.StatusCode >= 300 { return nil, HTTPError{Code: resp.StatusCode, Status: resp.Status, Reason: string(body)} diff --git a/fptcloud/object-storage/model_object_storage.go b/fptcloud/object-storage/model_object_storage.go new file mode 100644 index 0000000..1566c16 --- /dev/null +++ b/fptcloud/object-storage/model_object_storage.go @@ -0,0 +1,262 @@ +package fptcloud_object_storage + +type AbortIncompleteMultipartUpload struct { + DaysAfterInitiation int `json:"DaysAfterInitiation"` +} + +type AccessKey struct { + Credentials []struct { + ID string `json:"id"` + Credentials []struct { + AccessKey string `json:"accessKey"` + Active bool `json:"active"` + CreatedDate interface{} `json:"createdDate,omitempty"` + } `json:"credentials"` + } `json:"credentials"` +} + +type BucketAclRequest struct { + CannedAcl string `json:"cannedAcl"` + ApplyObjects bool `json:"applyObjects"` +} + +type BucketAclResponse struct { + Status bool `json:"status"` + Owner struct { + DisplayName string `json:"DisplayName"` + ID string `json:"ID"` + } `json:"Owner"` + Grants []struct { + Grantee struct { + DisplayName string `json:"DisplayName"` + ID string `json:"ID"` + Type string `json:"Type"` + } `json:"Grantee"` + Permission string `json:"Permission"` + } `json:"Grants"` + CannedACL string `json:"CannedACL"` +} + +type BucketCors struct { + CorsRules []CorsRule `json:"CORSRules"` +} + +type BucketCorsResponse struct { + Status bool `json:"status"` + CorsRules []struct { + ID string `json:"ID"` + AllowedHeaders []string `json:"AllowedHeaders,omitempty"` + AllowedMethods []string `json:"AllowedMethods"` + AllowedOrigins []string `json:"AllowedOrigins"` + ExposeHeaders []string `json:"ExposeHeaders,omitempty"` + MaxAgeSeconds int `json:"MaxAgeSeconds"` + } `json:"cors_rules"` + Total int `json:"total"` +} + +type BucketLifecycleResponse struct { + Status bool `json:"status"` + Rules []struct { + Expiration struct { + ExpiredObjectDeleteMarker bool `json:"ExpiredObjectDeleteMarker,omitempty"` + Days int `json:"Days,omitempty"` + } `json:"Expiration"` + ID string `json:"ID"` + Filter struct { + Prefix string `json:"Prefix"` + } `json:"Filter,omitempty"` + Status string `json:"Status"` + NoncurrentVersionExpiration struct { + NoncurrentDays int `json:"NoncurrentDays"` + } `json:"NoncurrentVersionExpiration"` + AbortIncompleteMultipartUpload struct { + DaysAfterInitiation int `json:"DaysAfterInitiation"` + } `json:"AbortIncompleteMultipartUpload"` + Prefix string `json:"Prefix,omitempty"` + } `json:"rules"` + Total int `json:"total"` +} + +type BucketPolicyRequest struct { + Policy string `json:"policy"` +} + +type BucketPolicyResponse struct { + Status bool `json:"status"` + Policy string `json:"policy"` +} + +type BucketRequest struct { + Name string `json:"name"` + Versioning string `json:"versioning,omitempty"` + Acl string `json:"acl"` +} + +type BucketVersioningRequest struct { + Status string `json:"status"` // "Enabled" or "Suspended" +} + +type BucketVersioningResponse struct { + Status bool `json:"status"` + Config string `json:"config"` // "Enabled" or "Suspended" +} + +type BucketWebsiteRequest struct { + Key string `json:"key"` + Suffix string `json:"suffix"` + Bucket string `json:"bucket"` +} + +type BucketWebsiteResponse struct { + Status bool `json:"status"` + Config struct { + ResponseMetadata struct { + RequestID string `json:"RequestId"` + HostID string `json:"HostId"` + HTTPStatusCode int `json:"HTTPStatusCode"` + HTTPHeaders struct { + XAmzRequestID string `json:"x-amz-request-id"` + ContentType string `json:"content-type"` + ContentLength string `json:"content-length"` + Date string `json:"date"` + } `json:"HTTPHeaders"` + RetryAttempts int `json:"RetryAttempts"` + } `json:"ResponseMetadata"` + IndexDocument struct { + Suffix string `json:"Suffix"` + } `json:"IndexDocument"` + ErrorDocument struct { + Key string `json:"Key"` + } `json:"ErrorDocument"` + } `json:"config,omitempty"` +} + +type CommonResponse struct { + Status bool `json:"status"` + Message string `json:"message,omitempty"` +} + +type CorsRule struct { + ID string `json:"ID,omitempty"` + AllowedOrigins []string `json:"AllowedOrigins"` + AllowedMethods []string `json:"AllowedMethods"` + ExposeHeaders []string `json:"ExposeHeaders,omitempty"` + AllowedHeaders []string `json:"AllowedHeaders,omitempty"` + MaxAgeSeconds int `json:"MaxAgeSeconds"` +} + +type CreateAccessKeyResponse struct { + Status bool `json:"status"` + Message string `json:"message,omitempty"` + Credential struct { + AccessKey string `json:"accessKey"` + SecretKey string `json:"secretKey"` + Active interface{} `json:"active"` + CreatedDate interface{} `json:"createdDate,omitempty"` + } `json:"credential,omitempty"` +} + +type DetailSubUser struct { + UserID string `json:"user_id"` + Arn interface{} `json:"arn,omitempty"` + Active bool `json:"active"` + Role string `json:"role"` + CreatedAt interface{} `json:"created_at,omitempty"` + AccessKeys []string `json:"access_keys"` +} + +type Expiration struct { + Days int `json:"Days,omitempty"` + ExpiredObjectDeleteMarker bool `json:"ExpiredObjectDeleteMarker,omitempty"` +} + +type Filter struct { + Prefix string `json:"Prefix"` +} + +type ListBucketResponse struct { + Buckets []struct { + Name string `json:"Name"` + CreationDate string `json:"CreationDate"` + IsEmpty bool `json:"isEmpty"` + S3ServiceID string `json:"s3_service_id"` + IsEnabledLogging bool `json:"isEnabledLogging"` + Endpoint string `json:"endpoint"` + } `json:"buckets"` + Total int `json:"total"` +} + +type NoncurrentVersionExpiration struct { + NoncurrentDays int `json:"NoncurrentDays"` +} + +type PutBucketAclResponse struct { + Status bool `json:"status"` + TaskID string `json:"taskId"` +} + +type S3BucketLifecycleConfig struct { + ID string `json:"ID"` + Filter Filter `json:"Filter"` + Expiration Expiration `json:"Expiration"` + NoncurrentVersionExpiration NoncurrentVersionExpiration `json:"NoncurrentVersionExpiration"` + AbortIncompleteMultipartUpload AbortIncompleteMultipartUpload `json:"AbortIncompleteMultipartUpload"` +} + +type S3ServiceEnableResponse struct { + Data []struct { + S3ServiceName string `json:"s3_service_name"` + S3ServiceID string `json:"s3_service_id"` + S3Platform string `json:"s3_platform"` + DefaultUser interface{} `json:"default_user,omitempty"` + MigrateQuota int `json:"migrate_quota"` + SyncQuota int `json:"sync_quota"` + RgwTotalNodes int `json:"rgw_total_nodes,omitempty"` + RgwUserActiveNodes int `json:"rgw_user_active_nodes,omitempty"` + HasUnusualConfig interface{} `json:"has_unusual_config,omitempty"` + } `json:"data"` + Total int `json:"total"` +} + +type Statement struct { + Sid string `json:"Sid"` + Effect string `json:"Effect"` + Principal map[string]interface{} `json:"Principal"` + Action []string `json:"Action"` + Resource []string `json:"Resource"` +} + +type SubUser struct { + Role string `json:"role"` + UserId string `json:"user_id"` +} + +type SubUserCreateKeyResponse struct { + Status bool `json:"status"` + Message string `json:"message,omitempty"` + Credential struct { + AccessKey string `json:"accessKey,omitempty"` + SecretKey string `json:"secretKey,omitempty"` + Active interface{} `json:"active,omitempty"` + CreatedDate interface{} `json:"createdDate,omitempty"` + } `json:"credential,omitempty"` +} + +type SubUserCreateRequest struct { + Username string `json:"username"` + DisplayName string `json:"display_name"` + Email string `json:"email"` + Permissions []string `json:"permissions"` +} + +type SubUserListResponse struct { + SubUsers []struct { + UserID string `json:"user_id"` + Arn string `json:"arn"` + Active bool `json:"active"` + Role string `json:"role"` + CreatedAt interface{} `json:"created_at,omitempty"` + AccessKeys interface{} `json:"access_keys,omitempty"` + } `json:"sub_users"` + Total int `json:"total"` +} diff --git a/fptcloud/object-storage/datasource_object_storage.go b/fptcloud/object-storage/object_storage_service.go similarity index 64% rename from fptcloud/object-storage/datasource_object_storage.go rename to fptcloud/object-storage/object_storage_service.go index 187c249..984d0c9 100644 --- a/fptcloud/object-storage/datasource_object_storage.go +++ b/fptcloud/object-storage/object_storage_service.go @@ -6,254 +6,6 @@ import ( common "terraform-provider-fptcloud/commons" ) -// SubUserCreateRequest represents the request body for creating a sub-user -type SubUserCreateRequest struct { - Username string `json:"username"` - DisplayName string `json:"display_name"` - Email string `json:"email"` - Permissions []string `json:"permissions"` -} -type AccessKey struct { - Credentials []struct { - ID string `json:"id"` - Credentials []struct { - AccessKey string `json:"accessKey"` - Active bool `json:"active"` - CreatedDate interface{} `json:"createdDate"` - } `json:"credentials"` - } `json:"credentials"` -} -type CreateAccessKeyResponse struct { - Status bool `json:"status"` - Message string `json:"message,omitempty"` - Credential struct { - AccessKey string `json:"accessKey"` - SecretKey string `json:"secretKey"` - Active interface{} `json:"active"` - CreatedDate interface{} `json:"createdDate"` - } `json:"credential,omitempty"` -} -type SubUserCreateKeyResponse struct { - Status bool `json:"status"` - Message string `json:"message,omitempty"` - Credential struct { - AccessKey string `json:"accessKey,omitempty"` - SecretKey string `json:"secretKey,omitempty"` - Active interface{} `json:"active,omitempty"` - CreatedDate interface{} `json:"createdDate,omitempty"` - } `json:"credential,omitempty"` -} - -type SubUser struct { - Role string `json:"role"` - UserId string `json:"user_id"` -} -type SubUserListResponse struct { - SubUsers []struct { - UserID string `json:"user_id"` - Arn string `json:"arn"` - Active bool `json:"active"` - Role string `json:"role"` - CreatedAt interface{} `json:"created_at"` - AccessKeys interface{} `json:"access_keys"` - } `json:"sub_users"` - Total int `json:"total"` -} -type CommonResponse struct { - Status bool `json:"status"` - Message string `json:"message,omitempty"` -} -type CorsRule struct { - ID string `json:"ID,omitempty"` - AllowedOrigins []string `json:"AllowedOrigins"` - AllowedMethods []string `json:"AllowedMethods"` - ExposeHeaders []string `json:"ExposeHeaders,omitempty"` - AllowedHeaders []string `json:"AllowedHeaders,omitempty"` - MaxAgeSeconds int `json:"MaxAgeSeconds"` -} -type BucketCors struct { - CorsRules []CorsRule `json:"CORSRules"` -} -type BucketCorsResponse struct { - Status bool `json:"status"` - CorsRules []struct { - ID string `json:"ID"` - AllowedHeaders []string `json:"AllowedHeaders,omitempty"` - AllowedMethods []string `json:"AllowedMethods"` - AllowedOrigins []string `json:"AllowedOrigins"` - ExposeHeaders []string `json:"ExposeHeaders,omitempty"` - MaxAgeSeconds int `json:"MaxAgeSeconds"` - } `json:"cors_rules"` - Total int `json:"total"` -} - -type BucketPolicyResponse struct { - Status bool `json:"status"` - Policy string `json:"policy"` -} -type BucketPolicyRequest struct { - Policy string `json:"policy"` -} -type Statement struct { - Sid string `json:"Sid"` - Effect string `json:"Effect"` - Principal map[string]interface{} `json:"Principal"` - Action []string `json:"Action"` - Resource []string `json:"Resource"` -} - -type BucketVersioningRequest struct { - Status string `json:"status"` // "Enabled" or "Suspended" -} -type BucketVersioningResponse struct { - Status bool `json:"status"` - Config string `json:"config"` // "Enabled" or "Suspended" -} - -type BucketAclResponse struct { - Status bool `json:"status"` - Owner struct { - DisplayName string `json:"DisplayName"` - ID string `json:"ID"` - } `json:"Owner"` - Grants []struct { - Grantee struct { - DisplayName string `json:"DisplayName"` - ID string `json:"ID"` - Type string `json:"Type"` - } `json:"Grantee"` - Permission string `json:"Permission"` - } `json:"Grants"` - CannedACL string `json:"CannedACL"` -} -type BucketAclRequest struct { - CannedAcl string `json:"cannedAcl"` - ApplyObjects bool `json:"applyObjects"` -} -type PutBucketAclResponse struct { - Status bool `json:"status"` - // TaskID may be empty if applyObjects is false, if applyObjects is true, the taskID will be returned - TaskID string `json:"taskId"` -} -type BucketWebsiteRequest struct { - Key string `json:"key"` - Suffix string `json:"suffix"` - Bucket string `json:"bucket"` -} -type BucketWebsiteResponse struct { - Status bool `json:"status"` - Config struct { - ResponseMetadata struct { - RequestID string `json:"RequestId"` - HostID string `json:"HostId"` - HTTPStatusCode int `json:"HTTPStatusCode"` - HTTPHeaders struct { - XAmzRequestID string `json:"x-amz-request-id"` - ContentType string `json:"content-type"` - ContentLength string `json:"content-length"` - Date string `json:"date"` - } `json:"HTTPHeaders"` - RetryAttempts int `json:"RetryAttempts"` - } `json:"ResponseMetadata"` - IndexDocument struct { - Suffix string `json:"Suffix"` - } `json:"IndexDocument"` - ErrorDocument struct { - Key string `json:"Key"` - } `json:"ErrorDocument"` - } `json:"config,omitempty"` -} - -type S3ServiceEnableResponse struct { - Data []struct { - S3ServiceName string `json:"s3_service_name"` - S3ServiceID string `json:"s3_service_id"` - S3Platform string `json:"s3_platform"` - DefaultUser interface{} `json:"default_user"` - MigrateQuota int `json:"migrate_quota"` - SyncQuota int `json:"sync_quota"` - RgwTotalNodes int `json:"rgw_total_nodes"` - RgwUserActiveNodes int `json:"rgw_user_active_nodes"` - HasUnusualConfig interface{} `json:"has_unusual_config"` - } `json:"data"` - Total int `json:"total"` -} - -// Bucket represents the response structure for a created bucket -type BucketRequest struct { - Name string `json:"name"` - Region string `json:"region"` - Versioning string `json:"versioning"` - Acl string `json:"acl"` -} -type ListBucketResponse struct { - Buckets []struct { - Name string `json:"Name"` - CreationDate string `json:"CreationDate"` - IsEmpty bool `json:"isEmpty"` - S3ServiceID string `json:"s3_service_id"` - IsEnabledLogging bool `json:"isEnabledLogging"` - Endpoint string `json:"endpoint"` - } `json:"buckets"` - Total int `json:"total"` -} -type BucketLifecycleResponse struct { - Status bool `json:"status"` - Rules []struct { - Expiration struct { - ExpiredObjectDeleteMarker bool `json:"ExpiredObjectDeleteMarker,omitempty"` - Days int `json:"Days,omitempty"` - } `json:"Expiration"` - ID string `json:"ID"` - Filter struct { - Prefix string `json:"Prefix"` - } `json:"Filter,omitempty"` - Status string `json:"Status"` - NoncurrentVersionExpiration struct { - NoncurrentDays int `json:"NoncurrentDays"` - } `json:"NoncurrentVersionExpiration"` - AbortIncompleteMultipartUpload struct { - DaysAfterInitiation int `json:"DaysAfterInitiation"` - } `json:"AbortIncompleteMultipartUpload"` - Prefix string `json:"Prefix,omitempty"` - } `json:"rules"` - Total int `json:"total"` -} - -type DetailSubUser struct { - UserID string `json:"user_id"` - Arn interface{} `json:"arn"` - Active bool `json:"active"` - Role string `json:"role"` - CreatedAt interface{} `json:"created_at"` - AccessKeys []string `json:"access_keys"` -} - -type S3BucketLifecycleConfig struct { - ID string `json:"ID"` - Filter Filter `json:"Filter"` - Expiration Expiration `json:"Expiration"` - NoncurrentVersionExpiration NoncurrentVersionExpiration `json:"NoncurrentVersionExpiration"` - AbortIncompleteMultipartUpload AbortIncompleteMultipartUpload `json:"AbortIncompleteMultipartUpload"` -} - -type Filter struct { - Prefix string `json:"Prefix"` -} - -type Expiration struct { - Days int `json:"Days,omitempty"` - ExpiredObjectDeleteMarker bool `json:"ExpiredObjectDeleteMarker,omitempty"` -} - -type NoncurrentVersionExpiration struct { - NoncurrentDays int `json:"NoncurrentDays"` -} - -type AbortIncompleteMultipartUpload struct { - DaysAfterInitiation int `json:"DaysAfterInitiation"` -} - // ObjectStorageService defines the interface for object storage operations type ObjectStorageService interface { CheckServiceEnable(vpcId string) S3ServiceEnableResponse @@ -265,7 +17,7 @@ type ObjectStorageService interface { // Access key ListAccessKeys(vpcId, s3ServiceId string) (AccessKey, error) - DeleteAccessKey(vpcId, s3ServiceId, accessKeyId string) error + DeleteAccessKey(vpcId, s3ServiceId, accessKeyId string) CommonResponse CreateAccessKey(vpcId, s3ServiceId string) *CreateAccessKeyResponse // Sub user @@ -318,12 +70,12 @@ func (s *ObjectStorageServiceImpl) CheckServiceEnable(vpcId string) S3ServiceEna apiPath := common.ApiPath.CheckS3ServiceEnable(vpcId) resp, err := s.client.SendGetRequest(apiPath) if err != nil { - return S3ServiceEnableResponse{} + return S3ServiceEnableResponse{Total: 0} } var response S3ServiceEnableResponse if err := json.Unmarshal(resp, &response); err != nil { - return S3ServiceEnableResponse{} + return S3ServiceEnableResponse{Total: 0} } return response } @@ -336,13 +88,13 @@ func (s *ObjectStorageServiceImpl) CreateBucket(req BucketRequest, vpcId, s3Serv return CommonResponse{Status: false, Message: err.Error()} } - var bucket BucketRequest + var bucket CommonResponse err = json.Unmarshal(resp, &bucket) if err != nil { return CommonResponse{Status: false, Message: err.Error()} } - return CommonResponse{Status: true, Message: "Bucket created successfully"} + return CommonResponse{Status: bucket.Status, Message: bucket.Message} } // CreateSubUser creates a new sub-user @@ -358,7 +110,6 @@ func (s *ObjectStorageServiceImpl) CreateSubUser(req SubUser, vpcId, s3ServiceId if err != nil { return &CommonResponse{Status: false, Message: err.Error()} } - return &CommonResponse{Status: subUser.Status, Message: "Sub-user created successfully"} } @@ -437,13 +188,14 @@ func (s *ObjectStorageServiceImpl) DeleteBucket(vpcId, s3ServiceId, bucketName s return CommonResponse{Status: true, Message: "Bucket deleted successfully"} } -func (s *ObjectStorageServiceImpl) DeleteAccessKey(vpcId, s3ServiceId, accessKeyId string) error { +func (s *ObjectStorageServiceImpl) DeleteAccessKey(vpcId, s3ServiceId, accessKeyId string) CommonResponse { apiPath := common.ApiPath.DeleteAccessKey(vpcId, s3ServiceId) body := map[string]string{"accessKey": accessKeyId} + if _, err := s.client.SendDeleteRequestWithBody(apiPath, body); err != nil { - return fmt.Errorf("failed to delete access key: %v", err) + return CommonResponse{Status: false, Message: err.Error()} } - return nil + return CommonResponse{Status: true, Message: "Access key deleted successfully"} } // Implement bucket policy methods diff --git a/fptcloud/object-storage/object_storage_service_test.go b/fptcloud/object-storage/object_storage_service_test.go new file mode 100644 index 0000000..8faf773 --- /dev/null +++ b/fptcloud/object-storage/object_storage_service_test.go @@ -0,0 +1,1027 @@ +package fptcloud_object_storage_test + +import ( + "testing" + + common "terraform-provider-fptcloud/commons" + fptcloud_object_storage "terraform-provider-fptcloud/fptcloud/object-storage" + + "github.com/stretchr/testify/assert" +) + +func TestCreateResourceAccessKey_ReturnsResourceAccessKeyIDWhenSuccess(t *testing.T) { + mockResponse := `{ + "status": true, + "message": "Create resource access key successfully", + "credential": { + "accessKey": "11111111-aaaa-1111-bbbb-111111111111", + "secretKey": "22222222-bbbb-2222-cccc-222222222222" + } + }` + mockClient, server, _ := common.NewClientForTesting(map[string]string{ + "/v1/vmware/vpc/vpc_id/s3/s3_service_id/user/credentials": mockResponse, + }) + defer server.Close() + service := fptcloud_object_storage.NewObjectStorageService(mockClient) + vpcId := "vpc_id" + s3ServiceId := "s3_service_id" + resourceAccessKeyID := service.CreateAccessKey(vpcId, s3ServiceId) + assert.NotNil(t, resourceAccessKeyID) + + assert.Equal(t, "11111111-aaaa-1111-bbbb-111111111111", resourceAccessKeyID.Credential.AccessKey) + assert.Equal(t, "22222222-bbbb-2222-cccc-222222222222", resourceAccessKeyID.Credential.SecretKey) + assert.Equal(t, true, resourceAccessKeyID.Status) + assert.Equal(t, "Create resource access key successfully", resourceAccessKeyID.Message) +} + +func TestCreateResourceAccessKey_ReturnsErrorWhenFailed(t *testing.T) { + mockResponse := `{ + "status": false, + "message": "Failed to create resource access key", + "credential": {} + }` + mockClient, server, _ := common.NewClientForTesting(map[string]string{ + "/v1/vmware/vpc/vpc_id/s3/s3_service_id/user/credentials": mockResponse, + }) + defer server.Close() + service := fptcloud_object_storage.NewObjectStorageService(mockClient) + vpcId := "vpc_id" + s3ServiceId := "s3_service_id" + resourceAccessKeyID := service.CreateAccessKey(vpcId, s3ServiceId) + assert.NotNil(t, resourceAccessKeyID) + + assert.Equal(t, "", resourceAccessKeyID.Credential.AccessKey) + assert.Equal(t, "", resourceAccessKeyID.Credential.SecretKey) + assert.Equal(t, false, resourceAccessKeyID.Status) + assert.Equal(t, "Failed to create resource access key", resourceAccessKeyID.Message) +} + +func TestDeleteResouurceAccessKey_ReturnOkWhenSuccess(t *testing.T) { + mockResponse := `{ + "status": true, + "message": "Delete resource access key successfully" + }` + mockClient, server, _ := common.NewClientForTesting(map[string]string{ + "/v1/vmware/vpc/vpc_id/s3/s3_service_id/user/credentials/credential_id": mockResponse, + }) + defer server.Close() + service := fptcloud_object_storage.NewObjectStorageService(mockClient) + vpcId := "vpc_id" + s3ServiceId := "s3_service_id" + credentialId := "credential_id" + res := service.DeleteAccessKey(vpcId, s3ServiceId, credentialId) + assert.NotNil(t, res) + assert.Equal(t, true, res.Status) + assert.Equal(t, "Access key deleted successfully", res.Message) +} + +func TestListAccessKeys_ReturnAccessKeysWhenSuccess(t *testing.T) { + mockResponse := `{ + "credentials": [ + { + "id": "credential_id", + "credentials": [ + { + "accessKey": "11111111-aaaa-1111-bbbb-111111111111", + "active": true + } + ] + } + ] + }` + mockClient, server, _ := common.NewClientForTesting(map[string]string{ + "/v1/vmware/vpc/vpc_id/s3/user/credentials?s3_service_id=s3_service_id": mockResponse, + }) + defer server.Close() + service := fptcloud_object_storage.NewObjectStorageService(mockClient) + vpcId := "vpc_id" + s3ServiceId := "s3_service_id" + accessKeys, _ := service.ListAccessKeys(vpcId, s3ServiceId) + assert.NotNil(t, accessKeys) + assert.Equal(t, "credential_id", accessKeys.Credentials[0].ID) + assert.Equal(t, "11111111-aaaa-1111-bbbb-111111111111", accessKeys.Credentials[0].Credentials[0].AccessKey) + assert.Equal(t, true, accessKeys.Credentials[0].Credentials[0].Active) +} + +func TestCreateBucket_ReturnsBucketIDWhenSuccess(t *testing.T) { + mockResponse := `{ + "status": true, + "message": "Create bucket successfully" + }` + mockClient, server, _ := common.NewClientForTesting(map[string]string{ + "/v1/vmware/vpc/vpc_id/s3/s3_service_id/bucket": mockResponse, + }) + defer server.Close() + service := fptcloud_object_storage.NewObjectStorageService(mockClient) + vpcId := "vpc_id" + s3ServiceId := "s3_service_id" + bucketRequest := fptcloud_object_storage.BucketRequest{ + Name: "bucket_name", + Acl: "private", + } + r := service.CreateBucket(bucketRequest, vpcId, s3ServiceId) + assert.NotNil(t, r) + assert.Equal(t, true, r.Status) +} + +func TestCreateBucket_ReturnsErrorWhenFailed(t *testing.T) { + mockResponse := `{ + "status": false, + "message": "Failed to create bucket", + }` + mockClient, server, _ := common.NewClientForTesting(map[string]string{ + "/v1/vmware/vpc/vpc_id/s3/s3_service_id/bucket": mockResponse, + }) + defer server.Close() + service := fptcloud_object_storage.NewObjectStorageService(mockClient) + vpcId := "vpc_id" + s3ServiceId := "s3_service_id" + bucketRequest := fptcloud_object_storage.BucketRequest{ + Name: "bucket_name", + Acl: "private", + } + r := service.CreateBucket(bucketRequest, vpcId, s3ServiceId) + assert.NotNil(t, r) + assert.Equal(t, false, r.Status) +} + +func TestListBuckets_ReturnsBucketsWhenSuccess(t *testing.T) { + mockResponse := `{ + "buckets": [ + { + "Name": "bucket_name", + "CreationDate": "2024-11-26T16:43:55.121000+00:00", + "isEmpty": false, + "s3_service_id": "s3_service_id", + "isEnabledLogging": false, + "endpoint": "https://xxxx-xxx.xyz.com" + } + ], + "total": 1 + }` + mockClient, server, _ := common.NewClientForTesting(map[string]string{ + "/v1/vmware/vpc/vpc_id/s3/buckets?page=5&page_size=10&s3_service_id=s3_service_id": mockResponse, + }) + defer server.Close() + service := fptcloud_object_storage.NewObjectStorageService(mockClient) + vpcId := "vpc_id" + s3ServiceId := "s3_service_id" + buckets := service.ListBuckets(vpcId, s3ServiceId, 5, 10) + assert.NotNil(t, buckets) + assert.Equal(t, "bucket_name", buckets.Buckets[0].Name) + assert.Equal(t, "2024-11-26T16:43:55.121000+00:00", buckets.Buckets[0].CreationDate) + assert.Equal(t, false, buckets.Buckets[0].IsEmpty) + assert.Equal(t, "s3_service_id", buckets.Buckets[0].S3ServiceID) + assert.Equal(t, false, buckets.Buckets[0].IsEnabledLogging) + assert.Equal(t, "https://xxxx-xxx.xyz.com", buckets.Buckets[0].Endpoint) +} + +func TestListBuckets_ReturnsErrorWhenFailed(t *testing.T) { + mockResponse := `{ + "buckets": [], + "total": 0 + }` + mockClient, server, _ := common.NewClientForTesting(map[string]string{ + "/v1/vmware/vpc/vpc_id/s3/buckets?page=5&page_size=10&s3_service_id=s3_service_id": mockResponse, + }) + defer server.Close() + service := fptcloud_object_storage.NewObjectStorageService(mockClient) + vpcId := "vpc_id" + s3ServiceId := "s3_service_id" + buckets := service.ListBuckets(vpcId, s3ServiceId, 5, 10) + assert.NotNil(t, buckets) + assert.Equal(t, 0, buckets.Total) +} + +func TestDeleteBucket_ReturnsOkWhenSuccess(t *testing.T) { + mockResponse := `{ + "status": true + }` + mockClient, server, _ := common.NewClientForTesting(map[string]string{ + "/v1/vmware/vpc/vpc_id/s3/s3_service_id": mockResponse, + }) + defer server.Close() + service := fptcloud_object_storage.NewObjectStorageService(mockClient) + vpcId := "vpc_id" + s3ServiceId := "s3_service_id" + bucketName := "bucket_name" + res := service.DeleteBucket(vpcId, s3ServiceId, bucketName) + assert.NotNil(t, res) + assert.Equal(t, true, res.Status) +} + +func TestCreateSubUser_ReturnsTrueWhenSuccess(t *testing.T) { + mockResponse := `{ + "status": true, + "message": "Sub-user created successfully" + }` + mockClient, server, _ := common.NewClientForTesting(map[string]string{ + "/v1/vmware/vpc/vpc_id/s3/s3_service_id/sub-users/create": mockResponse, + }) + defer server.Close() + service := fptcloud_object_storage.NewObjectStorageService(mockClient) + vpcId := "vpc_id" + s3ServiceId := "s3_service_id" + subUserRequest := fptcloud_object_storage.SubUser{ + Role: "admin", + UserId: "user_id", + } + r := service.CreateSubUser(subUserRequest, vpcId, s3ServiceId) + assert.NotNil(t, r) + assert.Equal(t, true, r.Status) + assert.Equal(t, "Sub-user created successfully", r.Message) +} + +func TestCreateSubUser_ReturnsFalseWhenFailed(t *testing.T) { + mockResponse := `{ + "status": false + }` + mockClient, server, _ := common.NewClientForTesting(map[string]string{ + "/v1/vmware/vpc/vpc_id/s3/s3_service_id/sub-users/wrong_endpoint": mockResponse, + }) + defer server.Close() + service := fptcloud_object_storage.NewObjectStorageService(mockClient) + vpcId := "vpc_id" + s3ServiceId := "s3_service_id" + subUserRequest := fptcloud_object_storage.SubUser{ + Role: "admin", + UserId: "user_id", + } + r := service.CreateSubUser(subUserRequest, vpcId, s3ServiceId) + assert.NotNil(t, r) + assert.Equal(t, false, r.Status) +} + +func TestDeleteSubUser_ReturnOkWhenSuccess(t *testing.T) { + mockResponse := `{}` + mockClient, server, _ := common.NewClientForTesting(map[string]string{ + "/v1/vmware/vpc/vpc_id/s3/s3_service_id/sub-users/sub_user_id/delete": mockResponse, + }) + defer server.Close() + service := fptcloud_object_storage.NewObjectStorageService(mockClient) + vpcId := "vpc_id" + s3ServiceId := "s3_service_id" + subUserId := "sub_user_id" + err := service.DeleteSubUser(vpcId, s3ServiceId, subUserId) + assert.Nil(t, err) +} + +func TestListSubUsers_ReturnsSubUsersWhenSuccess(t *testing.T) { + mockResponse := `{ + "sub_users": [ + { + "user_id": "sgn-replicate123123", + "arn": "arn:aws:iam:::user/xxx:sgn-replicate123123", + "active": true, + "role": "SubUserReadWrite" + } + ], + "total": 1 + }` + mockClient, server, _ := common.NewClientForTesting(map[string]string{ + "/v1/vmware/vpc/vpc_id/s3/s3_service_id/sub-users/list?page=5&page_size=25": mockResponse, + }) + defer server.Close() + service := fptcloud_object_storage.NewObjectStorageService(mockClient) + vpcId := "vpc_id" + s3ServiceId := "s3_service_id" + subUsers, err := service.ListSubUsers(vpcId, s3ServiceId, 5, 25) + assert.NotNil(t, subUsers) + assert.Nil(t, err) + assert.Equal(t, 1, subUsers.Total) + assert.Equal(t, "sgn-replicate123123", subUsers.SubUsers[0].UserID) + assert.Equal(t, "arn:aws:iam:::user/xxx:sgn-replicate123123", subUsers.SubUsers[0].Arn) + assert.Equal(t, true, subUsers.SubUsers[0].Active) + assert.Equal(t, "SubUserReadWrite", subUsers.SubUsers[0].Role) +} + +func TestListSubUsers_ReturnsErrorWhenFailed(t *testing.T) { + mockResponse := `{ + "sub_users": [], + "total": 0, + }` + mockClient, server, _ := common.NewClientForTesting(map[string]string{ + "/v1/vmware/vpc/vpc_id/s3/s3_service_id/sub-users/list?page=5&page_size=25": mockResponse, + }) + defer server.Close() + service := fptcloud_object_storage.NewObjectStorageService(mockClient) + vpcId := "vpc_id" + s3ServiceId := "s3_service_id" + subUsers, err := service.ListSubUsers(vpcId, s3ServiceId, 5, 25) + assert.NotNil(t, subUsers) + assert.NotNil(t, err) + assert.Equal(t, 0, subUsers.Total) +} + +func TestGetDetailSubUser_ReturnOkWhenSuccess(t *testing.T) { + mockResponse := ` + { + "user_id": "sgn-replicate123123", + "active": true, + "role": "SubUserReadWrite", + "access_keys": [] + } + ` + mockClient, server, _ := common.NewClientForTesting(map[string]string{ + "/v1/vmware/vpc/vpc_id/s3/s3_service_id/sub-users/sub_user_id": mockResponse, + }) + defer server.Close() + service := fptcloud_object_storage.NewObjectStorageService(mockClient) + vpcId := "vpc_id" + s3ServiceId := "s3_service_id" + subUserId := "sub_user_id" + subUser := service.DetailSubUser(vpcId, s3ServiceId, subUserId) + assert.NotNil(t, subUser) + assert.Equal(t, "sgn-replicate123123", subUser.UserID) + assert.Equal(t, true, subUser.Active) + assert.Equal(t, "SubUserReadWrite", subUser.Role) +} + +func TestCreateSubUserAccessKey_ReturnsAccessKeyWhenSuccess(t *testing.T) { + mockResponse := `{ + "status": true, + "credential": { + "accessKey": "example_access_key", + "secretKey": "example_secret_key" + } + }` + mockClient, server, _ := common.NewClientForTesting(map[string]string{ + "/v1/vmware/vpc/vpc_id/s3/s3_service_id/sub-users/sub_user_id/credentials/create": mockResponse, + }) + defer server.Close() + service := fptcloud_object_storage.NewObjectStorageService(mockClient) + vpcId := "vpc_id" + s3ServiceId := "s3_service_id" + subUserId := "sub_user_id" + accessKey := service.CreateSubUserAccessKey(vpcId, s3ServiceId, subUserId) + assert.NotNil(t, accessKey) + assert.Equal(t, "example_access_key", accessKey.Credential.AccessKey) + assert.Equal(t, "example_secret_key", accessKey.Credential.SecretKey) + assert.Equal(t, true, accessKey.Status) +} + +func TestCreateSubUserAccessKey_ReturnsErrorWhenFailed(t *testing.T) { + mockResponse := `{ + "status": false, + }` + mockClient, server, _ := common.NewClientForTesting(map[string]string{ + "/v1/vmware/vpc/vpc_id/s3/s3_service_id/sub-users/sub_user_id/credentials/create": mockResponse, + }) + defer server.Close() + service := fptcloud_object_storage.NewObjectStorageService(mockClient) + vpcId := "vpc_id" + s3ServiceId := "s3_service_id" + subUserId := "sub_user_id" + accessKey := service.CreateSubUserAccessKey(vpcId, s3ServiceId, subUserId) + assert.NotNil(t, accessKey) + assert.Equal(t, "", accessKey.Credential.AccessKey) + assert.Equal(t, "", accessKey.Credential.SecretKey) + assert.Equal(t, false, accessKey.Status) +} + +func TestDeleteSubUserAccessKey_ReturnOkWhenSuccess(t *testing.T) { + mockResponse := `{ + "status": true + }` + mockClient, server, _ := common.NewClientForTesting(map[string]string{ + "/v1/vmware/vpc/vpc_id/s3/s3_service_id/sub-users/sub_user_id/credentials/delete": mockResponse, + }) + defer server.Close() + service := fptcloud_object_storage.NewObjectStorageService(mockClient) + vpcId := "vpc_id" + s3ServiceId := "s3_service_id" + subUserId := "sub_user_id" + accessKeyId := "access_key_id" + res := service.DeleteSubUserAccessKey(vpcId, s3ServiceId, subUserId, accessKeyId) + assert.NotNil(t, res) + assert.Equal(t, true, res.Status) +} + +func TestPutBucketPolicy_ReturnOkWhenSuccess(t *testing.T) { + mockResponse := `{ + "status": true + }` + mockClient, server, _ := common.NewClientForTesting(map[string]string{ + "/v1/vmware/vpc/vpc_id/s3/s3_service_id/bucket/bucket_name/put-policy": mockResponse, + }) + defer server.Close() + service := fptcloud_object_storage.NewObjectStorageService(mockClient) + vpcId := "vpc_id" + s3ServiceId := "s3_service_id" + bucketName := "bucket_name" + policy := map[string]interface { + }{"Version": "2012-10-17"} + res := service.PutBucketPolicy(vpcId, s3ServiceId, bucketName, policy) + assert.NotNil(t, res) + assert.Equal(t, true, res.Status) +} + +func TestGetBucketPolicy_ReturnsPolicyWhenSuccess(t *testing.T) { + mockResponse := `{ + "policy": "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Sid\":\"AllowAllS3Actions\",\"Effect\":\"Allow\",\"Principal\":\"*\",\"Action\":\"s3:*\",\"Resource\":\"arn:aws:s3:::bucket_name/*\"}]}", + "status": true + }` + mockClient, server, _ := common.NewClientForTesting(map[string]string{ + "/v1/vmware/vpc/vpc_id/s3/s3_service_id/bucket/bucket_name/get-policy": mockResponse, + }) + defer server.Close() + service := fptcloud_object_storage.NewObjectStorageService(mockClient) + vpcId := "vpc_id" + s3ServiceId := "s3_service_id" + bucketName := "bucket_name" + policy := service.GetBucketPolicy(vpcId, s3ServiceId, bucketName) + assert.NotNil(t, policy) + assert.Equal(t, "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Sid\":\"AllowAllS3Actions\",\"Effect\":\"Allow\",\"Principal\":\"*\",\"Action\":\"s3:*\",\"Resource\":\"arn:aws:s3:::bucket_name/*\"}]}", policy.Policy) + assert.Equal(t, true, policy.Status) +} + +func TestGetBucketPolicy_ReturnsFalseWhenFailed(t *testing.T) { + mockResponse := `{ + "policy": "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Sid\":\"AllowAllS3Actions\",\"Effect\":\"Allow\",\"Principal\":\"*\",\"Action\":\"s3:*\",\"Resource\":\"arn:aws:s3:::bucket_name/*\"}]}", + "status": false, + }` + mockClient, server, _ := common.NewClientForTesting(map[string]string{ + "/v1/vmware/vpc/vpc_id/s3/s3_service_id/bucket/bucket_name/get-policy": mockResponse, + }) + defer server.Close() + service := fptcloud_object_storage.NewObjectStorageService(mockClient) + vpcId := "vpc_id" + s3ServiceId := "s3_service_id" + bucketName := "bucket_name" + policy := service.GetBucketPolicy(vpcId, s3ServiceId, bucketName) + assert.NotNil(t, policy) + assert.Equal(t, false, policy.Status) +} + +func TestCreateBucketCors_ReturnOkWhenSuccess(t *testing.T) { + mockResponse := `{ + "status": true + }` + mockClient, server, _ := common.NewClientForTesting(map[string]string{ + "/v1/vmware/vpc/vpc_id/s3/s3_service_id/bucket/bucket_name/create-bucket-cors": mockResponse, + }) + defer server.Close() + service := fptcloud_object_storage.NewObjectStorageService(mockClient) + bucketName := "bucket_name" + cors := map[string]interface{}{ + "AllowedHeaders": []string{"*"}, + } + res := service.CreateBucketCors("vpc_id", "s3_service_id", bucketName, cors) + assert.NotNil(t, res) + assert.Equal(t, true, res.Status) +} + +func TestUpdateBucketCors_ReturnOkWhenSuccess(t *testing.T) { + mockResponse := `{ + "status": true + }` + mockClient, server, _ := common.NewClientForTesting(map[string]string{ + "/v1/vmware/vpc/vpc_id/s3/s3_service_id/bucket/bucket_name/create-bucket-cors": mockResponse, + }) + defer server.Close() + service := fptcloud_object_storage.NewObjectStorageService(mockClient) + bucketName := "bucket_name" + cors := map[string]interface{}{ + "AllowedHeaders": []string{"*"}, + } + arrCors := append([]map[string]interface{}{}, cors) + res := service.UpdateBucketCors("vpc_id", "s3_service_id", bucketName, arrCors) + assert.NotNil(t, res) + assert.Equal(t, true, res.Status) +} + +func TestGetBucketCors_ReturnCorsWhenSuccess(t *testing.T) { + mockResponse := `{ + "cors_rules": [ + { + "AllowedHeaders": [ + "*" + ] + } + ], + "status": true, + "total": 1 + }` + mockClient, server, _ := common.NewClientForTesting(map[string]string{ + "/v1/vmware/vpc/vpc_id/s3/s3_service_id/bucket/bucket_name/cors?page=5&page_size=25": mockResponse, + }) + defer server.Close() + service := fptcloud_object_storage.NewObjectStorageService(mockClient) + bucketName := "bucket_name" + cors, err := service.GetBucketCors("vpc_id", "s3_service_id", bucketName, 5, 25) + assert.NotNil(t, cors) + assert.Nil(t, err) + assert.Equal(t, true, cors.Status) + assert.Equal(t, "*", cors.CorsRules[0].AllowedHeaders[0]) +} + +func TestGetBucketCors_ReturnFalseWhenFailed(t *testing.T) { + mockResponse := `{ + "cors_rules": [], + "status": false, + "total": 0, + }` + mockClient, server, _ := common.NewClientForTesting(map[string]string{ + "/v1/vmware/vpc/vpc_id/s3/s3_service_id/bucket/bucket_name/cors?page=5&page_size=25": mockResponse, + }) + defer server.Close() + service := fptcloud_object_storage.NewObjectStorageService(mockClient) + bucketName := "bucket_name" + cors, err := service.GetBucketCors("vpc_id", "s3_service_id", bucketName, 5, 25) + assert.Nil(t, cors) + assert.NotNil(t, err) +} + +func TestPutBucketVersioning_ReturnNilWhenSuccess(t *testing.T) { + mockResponse := `{ + "status": true + }` + mockClient, server, _ := common.NewClientForTesting(map[string]string{ + "/v1/vmware/vpc/vpc_id/s3/s3_service_id/bucket/bucket_name/put-versioning": mockResponse, + }) + defer server.Close() + service := fptcloud_object_storage.NewObjectStorageService(mockClient) + bucketName := "bucket_name" + versioning := fptcloud_object_storage.BucketVersioningRequest{ + Status: "Enabled", + } + res := service.PutBucketVersioning("vpc_id", "s3_service_id", bucketName, versioning) + assert.Nil(t, res) +} + +func TestGetBucketVersioning_ReturnBucketVersioning(t *testing.T) { + mockResponse := `{ + "status": true, + "config": "Enabled" + }` + mockClient, server, _ := common.NewClientForTesting(map[string]string{ + "/v1/vmware/vpc/vpc_id/s3/s3_service_id/bucket/bucket_name/get-versioning": mockResponse, + }) + defer server.Close() + service := fptcloud_object_storage.NewObjectStorageService(mockClient) + bucketName := "bucket_name" + versioning := service.GetBucketVersioning("vpc_id", "s3_service_id", bucketName) + assert.NotNil(t, versioning) + assert.Equal(t, true, versioning.Status) +} + +func TestPutBucketAcl_ReturnAclWhenSuccess(t *testing.T) { + mockResponse := `{ + "status": true, + "taskId": "task_id" + }` + mockClient, server, _ := common.NewClientForTesting(map[string]string{ + "/v1/vmware/vpc/vpc_id/s3/s3_service_id/bucket/bucket_name/acl": mockResponse, + }) + defer server.Close() + service := fptcloud_object_storage.NewObjectStorageService(mockClient) + bucketName := "bucket_name" + acl := fptcloud_object_storage.BucketAclRequest{ + CannedAcl: "private", + ApplyObjects: true, + } + res := service.PutBucketAcl("vpc_id", "s3_service_id", bucketName, acl) + assert.NotNil(t, res) + assert.Equal(t, true, res.Status) + assert.Equal(t, "task_id", res.TaskID) +} + +func TestGetBucketAcl_ReturnAclWhenSuccess(t *testing.T) { + mockResponse := `{ + "status": true, + "Owner": { + "DisplayName": "example_user_id", + "ID": "example_user_id" + }, + "Grants": [ + { + "Grantee": { + "DisplayName": "example_user_id", + "ID": "example_user_id", + "Type": "CanonicalUser" + }, + "Permission": "FULL_CONTROL" + } + ], + "CannedACL": "private" + }` + mockClient, server, _ := common.NewClientForTesting(map[string]string{ + "/v1/vmware/vpc/vpc_id/s3/s3_service_id/bucket/bucket_name/acl": mockResponse, + }) + defer server.Close() + service := fptcloud_object_storage.NewObjectStorageService(mockClient) + bucketName := "bucket_name" + acl := service.GetBucketAcl("vpc_id", "s3_service_id", bucketName) + assert.NotNil(t, acl) + assert.Equal(t, true, acl.Status) + assert.Equal(t, "example_user_id", acl.Owner.DisplayName) + assert.Equal(t, "example_user_id", acl.Owner.ID) + assert.Equal(t, "example_user_id", acl.Grants[0].Grantee.DisplayName) + assert.Equal(t, "example_user_id", acl.Grants[0].Grantee.ID) + assert.Equal(t, "CanonicalUser", acl.Grants[0].Grantee.Type) + assert.Equal(t, "FULL_CONTROL", acl.Grants[0].Permission) +} + +func TestGetBucketAcl_ReturnFalseWhenFailed(t *testing.T) { + mockResponse := `{ + "status": false + }` + mockClient, server, _ := common.NewClientForTesting(map[string]string{ + "/v1/vmware/vpc/vpc_id/s3/s3_service_id/bucket/bucket_name/acl-wrong-endpoint": mockResponse, + }) + defer server.Close() + service := fptcloud_object_storage.NewObjectStorageService(mockClient) + bucketName := "bucket_name" + acl := service.GetBucketAcl("vpc_id", "s3_service_id", bucketName) + assert.NotNil(t, acl) + assert.Equal(t, false, acl.Status) +} + +func TestGetBucketAcl_ReturnFalseWhenFailedUnmarshalJson(t *testing.T) { + mockResponse := `{ + "status": false,,, + }` + mockClient, server, _ := common.NewClientForTesting(map[string]string{ + "/v1/vmware/vpc/vpc_id/s3/s3_service_id/bucket/bucket_name/acl-wrong-endpoint": mockResponse, + }) + defer server.Close() + service := fptcloud_object_storage.NewObjectStorageService(mockClient) + bucketName := "bucket_name" + acl := service.GetBucketAcl("vpc_id", "s3_service_id", bucketName) + assert.NotNil(t, acl) + assert.Equal(t, false, acl.Status) +} + +func TestPutBucketWebsite_ReturnOkWhenSuccess(t *testing.T) { + mockResponse := `{ + "status": true, + }` + mockClient, server, _ := common.NewClientForTesting(map[string]string{ + "/v1/vmware/vpc/vpc_id/s3/s3_service_id/bucket/bucket_name/put-config": mockResponse, + }) + defer server.Close() + service := fptcloud_object_storage.NewObjectStorageService(mockClient) + bucketName := "bucket_name" + website := fptcloud_object_storage.BucketWebsiteRequest{ + Key: "index.html", + Suffix: "index2.html", + Bucket: "bucket_name", + } + res := service.PutBucketWebsite("vpc_id", "s3_service_id", bucketName, website) + assert.NotNil(t, res) + assert.Equal(t, true, res.Status) +} + +func TestPutBucketWebsite_ReturnOFalseWhenFailed(t *testing.T) { + mockResponse := `{ + "status": false, + }` + mockClient, server, _ := common.NewClientForTesting(map[string]string{ + "/v1/vmware/vpc/vpc_id/s3/s3_service_id/bucket/bucket_name/put-config": mockResponse, + }) + defer server.Close() + service := fptcloud_object_storage.NewObjectStorageService(mockClient) + bucketName := "bucket_name" + website := fptcloud_object_storage.BucketWebsiteRequest{ + Key: "index.html", + Suffix: "index2.html", + Bucket: "bucket_name", + } + res := service.PutBucketWebsite("vpc_id", "s3_service_id", bucketName, website) + assert.NotNil(t, res) + assert.Equal(t, true, res.Status) +} + +func TestDeleteBucketStaticWebsite_ReturnTrueWhenSuccess(t *testing.T) { + mockResponse := `{ + "status": true + }` + mockClient, server, _ := common.NewClientForTesting(map[string]string{ + "/v1/vmware/vpc/vpc_id/s3/s3_service_id/bucket/bucket_name/delete-config": mockResponse, + }) + defer server.Close() + service := fptcloud_object_storage.NewObjectStorageService(mockClient) + bucketName := "bucket_name" + res := service.DeleteBucketStaticWebsite("vpc_id", "s3_service_id", bucketName) + assert.NotNil(t, res) + assert.Equal(t, true, res.Status) +} + +func TestDeleteBucketStaticWebsite_ReturnFalseWhenError(t *testing.T) { + mockResponse := `{ + "status": false + }` + mockClient, server, _ := common.NewClientForTesting(map[string]string{ + "/v1/vmware/vpc/vpc_id/s3/s3_service_id/bucket/bucket_name/delete-config-wrong-endpoint": mockResponse, + }) + defer server.Close() + service := fptcloud_object_storage.NewObjectStorageService(mockClient) + bucketName := "bucket_name" + res := service.DeleteBucketStaticWebsite("vpc_id", "s3_service_id", bucketName) + assert.NotNil(t, res) + assert.Equal(t, true, res.Status) +} + +func TestGetBucketWebsite_ReturnWebsiteWhenSuccess(t *testing.T) { + mockResponse := `{ + "status": true, + "config": { + "ResponseMetadata": { + "RequestId": "tx000000976595dcbf0f8e1-006746c273-326c5-han02-1", + "HostId": "", + "HTTPStatusCode": 200, + "HTTPHeaders": { + "x-amz-request-id": "tx000000976595dcbf0f8e1-006746c273-326c5-han02-1", + "content-type": "application/xml", + "content-length": "241", + "date": "Wed, 27 Nov 2024 06:55:47 GMT", + "strict-transport-security": "max-age=16000000; includeSubDomains; preload;", + "access-control-allow-origin": "*" + }, + "RetryAttempts": 0 + }, + "IndexDocument": { + "Suffix": "index.html" + }, + "ErrorDocument": { + "Key": "error.html" + } + } + }` + mockClient, server, _ := common.NewClientForTesting(map[string]string{ + "/v1/vmware/vpc/vpc_id/s3/s3_service_id/bucket/bucket_name/get-config": mockResponse, + }) + defer server.Close() + service := fptcloud_object_storage.NewObjectStorageService(mockClient) + bucketName := "bucket_name" + website := service.GetBucketWebsite("vpc_id", "s3_service_id", bucketName) + assert.NotNil(t, website) + assert.Equal(t, true, website.Status) + assert.Equal(t, "index.html", website.Config.IndexDocument.Suffix) + assert.Equal(t, "error.html", website.Config.ErrorDocument.Key) +} + +func TestGetBucketWebsite_ReturnFalseWhenError(t *testing.T) { + mockResponse := `{ + "status": false + }` + mockClient, server, _ := common.NewClientForTesting(map[string]string{ + "/v1/vmware/vpc/vpc_id/s3/s3_service_id/bucket/bucket_name/get-config-wrong-endpoint": mockResponse, + }) + defer server.Close() + service := fptcloud_object_storage.NewObjectStorageService(mockClient) + bucketName := "bucket_name" + website := service.GetBucketWebsite("vpc_id", "s3_service_id", bucketName) + assert.NotNil(t, website) + assert.Equal(t, false, website.Status) +} + +func TestGetBucketLifecycle_ReturnRuleWhenSuccess(t *testing.T) { + mockResponse := `{ + "status": true, + "rules": [ + { + "ID": "rule_id", + "Prefix": "prefix", + "Status": "Enabled", + "Expiration": { + "Days": 30 + } + } + ], + "total": 1 + }` + mockClient, server, _ := common.NewClientForTesting(map[string]string{ + "/v1/vmware/vpc/vpc_id/s3/s3_service_id/bucket/bucket_name/lifecycles?page=5&page_size=25": mockResponse, + }) + defer server.Close() + service := fptcloud_object_storage.NewObjectStorageService(mockClient) + bucketName := "bucket_name" + lifecycle := service.GetBucketLifecycle("vpc_id", "s3_service_id", bucketName, 5, 25) + assert.NotNil(t, lifecycle) + assert.Equal(t, true, lifecycle.Status) + assert.Equal(t, "rule_id", lifecycle.Rules[0].ID) + assert.Equal(t, "prefix", lifecycle.Rules[0].Prefix) + assert.Equal(t, "Enabled", lifecycle.Rules[0].Status) + assert.Equal(t, 30, lifecycle.Rules[0].Expiration.Days) + assert.Equal(t, 1, lifecycle.Total) +} + +func TestGetBucketLifecycle_ReturnFalseWhenFailed(t *testing.T) { + mockResponse := `{ + "status": false, + "rules": [], + "total": 0 + }` + mockClient, server, _ := common.NewClientForTesting(map[string]string{ + "/v1/vmware/vpc/vpc_id/s3/s3_service_id/bucket/bucket_name/lifecycles-wrong-endpoint?page=5&page_size=25": mockResponse, + }) + defer server.Close() + service := fptcloud_object_storage.NewObjectStorageService(mockClient) + bucketName := "bucket_name" + lifecycle := service.GetBucketLifecycle("vpc_id", "s3_service_id", bucketName, 5, 25) + assert.NotNil(t, lifecycle) + assert.Equal(t, false, lifecycle.Status) + assert.Equal(t, 0, lifecycle.Total) +} + +func TestPutBucketLifecycle_ReturnOkWhenSuccess(t *testing.T) { + mockResponse := `{ + "status": true + }` + mockClient, server, _ := common.NewClientForTesting(map[string]string{ + "/v1/vmware/vpc/vpc_id/s3/s3_service_id/bucket/bucket_name/create-bucket-lifecycle-configuration": mockResponse, + }) + defer server.Close() + service := fptcloud_object_storage.NewObjectStorageService(mockClient) + bucketName := "bucket_name" + rule := map[string]interface{}{ + "ID": "rule_id", + "Prefix": "prefix", + "Status": "Enabled", + "Expiration": map[string]interface{}{ + "Days": 30, + }, + } + res := service.PutBucketLifecycle("vpc_id", "s3_service_id", bucketName, rule) + assert.NotNil(t, res) + assert.Equal(t, true, res.Status) +} + +func TestPutBucketLifecycle_ReturnFalseWhenError(t *testing.T) { + mockResponse := `{ + "status": false + }` + mockClient, server, _ := common.NewClientForTesting(map[string]string{ + "/v1/vmware/vpc/vpc_id/s3/s3_service_id/bucket/bucket_name/create-bucket-lifecycle-configuration-wrong-endpoint": mockResponse, + }) + defer server.Close() + service := fptcloud_object_storage.NewObjectStorageService(mockClient) + bucketName := "bucket_name" + rule := map[string]interface{}{ + "ID": "rule_id", + "Prefix": "prefix", + "Status": "Enabled", + "Expiration": map[string]interface{}{ + "Days": 30, + }, + } + res := service.PutBucketLifecycle("vpc_id", "s3_service_id", bucketName, rule) + assert.NotNil(t, res) + assert.Equal(t, false, res.Status) +} + +func TestPutBucketLifecycle_ReturnFalseWhenErrorUnmarshalJson(t *testing.T) { + mockResponse := `{ + "status": false,,,,@#$@#$234 + }` + mockClient, server, _ := common.NewClientForTesting(map[string]string{ + "/v1/vmware/vpc/vpc_id/s3/s3_service_id/bucket/bucket_name/create-bucket-lifecycle-configuration-wrong-endpoint": mockResponse, + }) + defer server.Close() + service := fptcloud_object_storage.NewObjectStorageService(mockClient) + bucketName := "bucket_name" + rule := map[string]interface{}{ + "ID": "rule_id", + "Prefix": "prefix", + "Status": "Enabled", + "Expiration": map[string]interface{}{ + "Days": 30, + }, + } + res := service.PutBucketLifecycle("vpc_id", "s3_service_id", bucketName, rule) + assert.NotNil(t, res) + assert.Equal(t, false, res.Status) +} + +func TestDeleteBucketLifecycle_ReturnOkWhenSuccess(t *testing.T) { + mockResponse := `{ + "status": true + }` + mockClient, server, _ := common.NewClientForTesting(map[string]string{ + "/v1/vmware/vpc/vpc_id/s3/s3_service_id/bucket/bucket_name/delete-bucket-lifecycle-configuration": mockResponse, + }) + defer server.Close() + service := fptcloud_object_storage.NewObjectStorageService(mockClient) + bucketName := "bucket_name" + rule := map[string]interface{}{ + "ID": "rule_id", + "Prefix": "prefix", + "Status": "Enabled", + "Expiration": map[string]interface{}{ + "Days": 30, + }, + } + res := service.DeleteBucketLifecycle("vpc_id", "s3_service_id", bucketName, rule) + assert.NotNil(t, res) + assert.Equal(t, true, res.Status) +} + +func TestDeleteBucketLifecycle_ReturnFalseWhenError(t *testing.T) { + mockResponse := `{ + "status": false + }` + mockClient, server, _ := common.NewClientForTesting(map[string]string{ + "/v1/vmware/vpc/vpc_id/s3/s3_service_id/bucket/bucket_name/delete-bucket-lifecycle-configuration-wrong-endpoint": mockResponse, + }) + defer server.Close() + service := fptcloud_object_storage.NewObjectStorageService(mockClient) + bucketName := "bucket_name" + rule := map[string]interface{}{ + "ID": "rule_id", + "Prefix": "prefix", + "Status": "Enabled", + "Expiration": map[string]interface{}{ + "Days": 30, + }, + } + res := service.DeleteBucketLifecycle("vpc_id", "s3_service_id", bucketName, rule) + assert.NotNil(t, res) + assert.Equal(t, false, res.Status) +} + +func TestDeleteBucketLifecycle_ReturnFalseWhenErrorUnmarshalJson(t *testing.T) { + mockResponse := `{ + "status": false,,,,@#$@#$234 + }` + mockClient, server, _ := common.NewClientForTesting(map[string]string{ + "/v1/vmware/vpc/vpc_id/s3/s3_service_id/bucket/bucket_name/delete-bucket-lifecycle-configuration-wrong-endpoint": mockResponse, + }) + defer server.Close() + service := fptcloud_object_storage.NewObjectStorageService(mockClient) + bucketName := "bucket_name" + rule := map[string]interface{}{ + "ID": "rule_id", + "Prefix": "prefix", + "Status": "Enabled", + "Expiration": map[string]interface{}{ + "Days": 30, + }, + } + res := service.DeleteBucketLifecycle("vpc_id", "s3_service_id", bucketName, rule) + assert.NotNil(t, res) + assert.Equal(t, false, res.Status) +} + +func TestCheckServiceEnable_ReturnServicesWhenSuccess(t *testing.T) { + mockResponse := `{ + "data": [ + { + "s3_service_name": "HN-02", + "s3_service_id": "s3_service_id", + "s3_platform": "ceph", + "default_user": "fake-default-user", + "migrate_quota": 3, + "sync_quota": 3, + "rgw_total_nodes": 4, + "rgw_user_active_nodes": 2 + } + ], + "total": 1 + }` + mockClient, server, _ := common.NewClientForTesting(map[string]string{ + "/v1/vmware/vpc/vpc_id/s3/check-service-enabled?check_unlimited=undefined": mockResponse, + }) + + defer server.Close() + service := fptcloud_object_storage.NewObjectStorageService(mockClient) + vpcId := "vpc_id" + services := service.CheckServiceEnable(vpcId) + assert.NotNil(t, services) + assert.Equal(t, 1, services.Total) + assert.Equal(t, "HN-02", services.Data[0].S3ServiceName) + assert.Equal(t, "s3_service_id", services.Data[0].S3ServiceID) + assert.Equal(t, "ceph", services.Data[0].S3Platform) +} + +func TestCheckServiceEnable_ReturnFalseWhenError(t *testing.T) { + mockResponse := `{ + "total": 0 + }` + mockClient, server, _ := common.NewClientForTesting(map[string]string{ + "/v1/vmware/vpc/vpc_id/s3/check-service-enabled?check_unlimited=wrong-param": mockResponse, + }) + + defer server.Close() + service := fptcloud_object_storage.NewObjectStorageService(mockClient) + vpcId := "vpc_id" + services := service.CheckServiceEnable(vpcId) + assert.NotNil(t, services) + assert.Equal(t, 0, services.Total) +} + +func TestCheckServiceEnable_ReturnFalseWhenErrorUnmarshal(t *testing.T) { + mockResponse := `{ + "total": #$%#$%#$%#$%#$%!@#!23, + }` + mockClient, server, _ := common.NewClientForTesting(map[string]string{ + "/v1/vmware/vpc/vpc_id/s3/check-service-enabled?check_unlimited=wrong-param": mockResponse, + }) + + defer server.Close() + service := fptcloud_object_storage.NewObjectStorageService(mockClient) + vpcId := "vpc_id" + services := service.CheckServiceEnable(vpcId) + assert.NotNil(t, services) + assert.Equal(t, 0, services.Total) +} diff --git a/fptcloud/object-storage/resource_access_key.go b/fptcloud/object-storage/resource_access_key.go index 8914685..8af42ec 100644 --- a/fptcloud/object-storage/resource_access_key.go +++ b/fptcloud/object-storage/resource_access_key.go @@ -148,17 +148,15 @@ func resourceAccessKeyDelete(ctx context.Context, d *schema.ResourceData, m inte return diag.FromErr(fmt.Errorf("region %s is not enabled", regionName)) } - log.Printf("[DEBUG] Found S3 service ID: %s", s3ServiceDetail.S3ServiceId) - if accessKeyId == "" { log.Printf("[ERROR] access_key_id is empty") return diag.Errorf("access_key_id is required for deletion") } - err := service.DeleteAccessKey(vpcId, s3ServiceDetail.S3ServiceId, accessKeyId) - if err != nil { - log.Printf("[ERROR] Failed to delete access key %s: %v", accessKeyId, err) - return diag.FromErr(err) + data := service.DeleteAccessKey(vpcId, s3ServiceDetail.S3ServiceId, accessKeyId) + if !data.Status { + log.Printf("[ERROR] Failed to delete access key %s: %v", accessKeyId, data.Message) + return diag.Errorf("failed to delete access key %s: %s", accessKeyId, data.Message) } if err := d.Set("status", true); err != nil { d.SetId("")