Skip to content

Commit

Permalink
[Object Storage] update: fix config bucket lifecycle cannot create
Browse files Browse the repository at this point in the history
  • Loading branch information
hoanglm committed Nov 14, 2024
1 parent 0305e99 commit a997f3a
Show file tree
Hide file tree
Showing 7 changed files with 337 additions and 55 deletions.
2 changes: 1 addition & 1 deletion commons/api_path.go
Original file line number Diff line number Diff line change
Expand Up @@ -312,7 +312,7 @@ var ApiPath = struct {
return fmt.Sprintf("/v1/vmware/vpc/%s/s3/%s/bucket/%s/lifecycles?page=%d&page_size=%d", vpcId, s3ServiceId, bucketName, page, pageSize)
},
PutBucketLifecycle: func(vpcId, s3ServiceId, bucketName string) string {
return fmt.Sprintf("/v1/vmware/vpc/%s/s3/%s/bucket/%s/create-bucket-lifecycle-configuration`", vpcId, s3ServiceId, bucketName)
return fmt.Sprintf("/v1/vmware/vpc/%s/s3/%s/bucket/%s/create-bucket-lifecycle-configuration", vpcId, s3ServiceId, bucketName)
},
DeleteBucketLifecycle: func(vpcId, s3ServiceId, bucketName string) string {
return fmt.Sprintf("/v1/vmware/vpc/%s/s3/%s/bucket/%s/delete-bucket-lifecycle-configuration", vpcId, s3ServiceId, bucketName)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
resource "fptcloud_object_storage_bucket_policy" "example_bucket_policy" {
vpc_id = "your_vpc_id"
region_name = "your_region_name"
bucket_name = "your_bucket_name"

// Option 1: Load policy from file
policy_file = file("${path.module}/your_bucket_policy_json_content.json")

// Option 2: Inline policy
// policy = jsonencode({
// Version = "2012-10-17"
// Statement = [
// {
// Sid = "PublicReadGetObject"
// Effect = "Allow"
// Principal = "*"
// Action = "s3:GetObject"
// Resource = "arn:aws:s3:::example-bucket/*"
// }
// ]
// })
}
// NOTE: In case wanna delete bucket policy, just ignore policy_file and policy fields
output "bucket_policy" {
value = fptcloud_object_storage_bucket_policy.example_bucket_policy.status
}
58 changes: 42 additions & 16 deletions fptcloud/object-storage/datasource_object_storage.go
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,8 @@ type BucketLifecycleResponse struct {
Status bool `json:"status"`
Rules []struct {
Expiration struct {
ExpiredObjectDeleteMarker bool `json:"ExpiredObjectDeleteMarker"`
ExpiredObjectDeleteMarker bool `json:"ExpiredObjectDeleteMarker,omitempty"`
Days int `json:"Days,omitempty"`
} `json:"Expiration"`
ID string `json:"ID"`
Filter struct {
Expand All @@ -228,6 +229,31 @@ type DetailSubUser struct {
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
Expand All @@ -251,7 +277,7 @@ type ObjectStorageService interface {
DeleteSubUserAccessKey(vpcId, s3ServiceId, subUserId, accessKeyId string) CommonResponse

// bucket configuration
PutBucketPolicy(vpcId, s3ServiceId, bucketName string, policy BucketPolicyRequest) CommonResponse
PutBucketPolicy(vpcId, s3ServiceId, bucketName string, policy interface{}) CommonResponse
GetBucketPolicy(vpcId, s3ServiceId, bucketName string) *BucketPolicyResponse

// CORS configuration
Expand All @@ -274,8 +300,8 @@ type ObjectStorageService interface {

// Lifecycle configuration
GetBucketLifecycle(vpcId, s3ServiceId, bucketName string, page, pageSize int) (*BucketLifecycleResponse, error)
PutBucketLifecycle(vpcId, s3ServiceId, bucketName string, lifecycle interface{}) (*BucketLifecycleResponse, error)
DeleteBucketLifecycle(vpcId, s3ServiceId, bucketName string, lifecycle interface{}) (*BucketLifecycleResponse, error)
PutBucketLifecycle(vpcId, s3ServiceId, bucketName string, lifecycle map[string]interface{}) CommonResponse
DeleteBucketLifecycle(vpcId, s3ServiceId, bucketName string, lifecycle map[string]interface{}) CommonResponse
}

// ObjectStorageServiceImpl is the implementation of ObjectStorageService
Expand Down Expand Up @@ -421,7 +447,7 @@ func (s *ObjectStorageServiceImpl) DeleteAccessKey(vpcId, s3ServiceId, accessKey
}

// Implement bucket policy methods
func (s *ObjectStorageServiceImpl) PutBucketPolicy(vpcId, s3ServiceId, bucketName string, policy BucketPolicyRequest) CommonResponse {
func (s *ObjectStorageServiceImpl) PutBucketPolicy(vpcId, s3ServiceId, bucketName string, policy interface{}) CommonResponse {
apiPath := common.ApiPath.PutBucketPolicy(vpcId, s3ServiceId, bucketName)
if _, err := s.client.SendPutRequest(apiPath, policy); err != nil {
return CommonResponse{Status: false}
Expand Down Expand Up @@ -575,32 +601,32 @@ func (s *ObjectStorageServiceImpl) GetBucketLifecycle(vpcId, s3ServiceId, bucket
return &bucketLifecycle, nil
}

func (s *ObjectStorageServiceImpl) PutBucketLifecycle(vpcId, s3ServiceId, bucketName string, lifecycle interface{}) (*BucketLifecycleResponse, error) {
func (s *ObjectStorageServiceImpl) PutBucketLifecycle(vpcId, s3ServiceId, bucketName string, lifecycle map[string]interface{}) CommonResponse {
apiPath := common.ApiPath.PutBucketLifecycle(vpcId, s3ServiceId, bucketName)
resp, err := s.client.SendPutRequest(apiPath, lifecycle)
resp, err := s.client.SendPostRequest(apiPath, lifecycle)
if err != nil {
return nil, fmt.Errorf("failed to put bucket lifecycle: %v", err)
return CommonResponse{Status: false, Message: err.Error()}
}

var bucketLifecycle BucketLifecycleResponse
var bucketLifecycle CommonResponse
if err := json.Unmarshal(resp, &bucketLifecycle); err != nil {
return nil, fmt.Errorf("failed to unmarshal bucket lifecycle: %v", err)
return CommonResponse{Status: false, Message: err.Error()}
}
return &bucketLifecycle, nil
return bucketLifecycle
}

func (s *ObjectStorageServiceImpl) DeleteBucketLifecycle(vpcId, s3ServiceId, bucketName string, lifecycle interface{}) (*BucketLifecycleResponse, error) {
func (s *ObjectStorageServiceImpl) DeleteBucketLifecycle(vpcId, s3ServiceId, bucketName string, lifecycle map[string]interface{}) CommonResponse {
apiPath := common.ApiPath.DeleteBucketLifecycle(vpcId, s3ServiceId, bucketName)
resp, err := s.client.SendPutRequest(apiPath, lifecycle)
if err != nil {
return nil, fmt.Errorf("failed to delete bucket lifecycle: %v", err)
return CommonResponse{Status: false, Message: err.Error()}
}

var bucketLifecycle BucketLifecycleResponse
var bucketLifecycle CommonResponse
if err := json.Unmarshal(resp, &bucketLifecycle); err != nil {
return nil, fmt.Errorf("failed to unmarshal bucket lifecycle: %v", err)
return CommonResponse{Status: false, Message: err.Error()}
}
return &bucketLifecycle, nil
return bucketLifecycle
}

func (s *ObjectStorageServiceImpl) CreateSubUserAccessKey(vpcId, s3ServiceId, subUserId string) *SubUserCreateKeyResponse {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import (

func DataSourceBucketLifecycle() *schema.Resource {
return &schema.Resource{
ReadContext: dataSourceBucketLifecycle,
ReadContext: dataSourceBucketLifecycleRead,
Schema: map[string]*schema.Schema{
"vpc_id": {
Type: schema.TypeString,
Expand Down Expand Up @@ -47,9 +47,17 @@ func DataSourceBucketLifecycle() *schema.Resource {
Type: schema.TypeString,
Computed: true,
},
"prefix": {
Type: schema.TypeString,
"filter": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"prefix": {
Type: schema.TypeString,
Computed: true,
},
},
},
},
"status": {
Type: schema.TypeString,
Expand Down Expand Up @@ -98,7 +106,7 @@ func DataSourceBucketLifecycle() *schema.Resource {
}
}

func dataSourceBucketLifecycle(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
func dataSourceBucketLifecycleRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
client := m.(*common.Client)
service := NewObjectStorageService(client)

Expand Down Expand Up @@ -130,28 +138,43 @@ func dataSourceBucketLifecycle(ctx context.Context, d *schema.ResourceData, m in
if lifeCycleResponse.Total == 0 {
d.Set("life_cycle_rules", formattedData)

Check failure on line 139 in fptcloud/object-storage/datasource_object_storage_bucket_lifecycle.go

View workflow job for this annotation

GitHub Actions / test (ubuntu-latest)

Error return value of `d.Set` is not checked (errcheck)
}
for _, rule := range lifeCycleResponse.Rules {
formattedData = append(formattedData, map[string]interface{}{
"id": rule.ID,
"prefix": rule.Prefix,
"status": rule.Status,
"expiration": []interface{}{
for _, lifecycleRule := range lifeCycleResponse.Rules {
data := map[string]interface{}{
"id": lifecycleRule.ID,
"status": lifecycleRule.Status,
"noncurrent_version_expiration": []interface{}{
map[string]interface{}{
"expired_object_delete_marker": rule.Expiration.ExpiredObjectDeleteMarker,
"noncurrent_days": lifecycleRule.NoncurrentVersionExpiration.NoncurrentDays,
},
},
"noncurrent_version_expiration": []interface{}{
"abort_incomplete_multipart_upload": []interface{}{
map[string]interface{}{
"noncurrent_days": rule.NoncurrentVersionExpiration.NoncurrentDays,
"days_after_initiation": lifecycleRule.AbortIncompleteMultipartUpload.DaysAfterInitiation,
},
},
"abort_incomplete_multipart_upload": []interface{}{
"filter": []interface{}{
map[string]interface{}{
"days_after_initiation": rule.AbortIncompleteMultipartUpload.DaysAfterInitiation,
"prefix": lifecycleRule.Filter.Prefix,
},
},
})
}
if lifecycleRule.Expiration.Days != 0 {
data["expiration"] = []interface{}{
map[string]interface{}{
"days": lifecycleRule.Expiration.Days,
},
}
}
if lifecycleRule.Expiration.ExpiredObjectDeleteMarker {
data["expiration"] = []interface{}{
map[string]interface{}{
"expired_object_delete_marker": lifecycleRule.Expiration.ExpiredObjectDeleteMarker,
},
}
}
formattedData = append(formattedData, data)
}
fmt.Println("DEBUG: formattedData", formattedData)
if err := d.Set("life_cycle_rules", formattedData); err != nil {
d.SetId("")
return diag.FromErr(err)
Expand Down
Loading

0 comments on commit a997f3a

Please sign in to comment.