alibabacloudstack/resource_apsarastack_oss_bucket_object.go (258 lines of code) (raw):
package alibabacloudstack
import (
"bytes"
"fmt"
"io"
"log"
"time"
"strings"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
"github.com/aliyun/aliyun-oss-go-sdk/oss"
"github.com/aliyun/terraform-provider-alibabacloudstack/alibabacloudstack/connectivity"
"github.com/aliyun/terraform-provider-alibabacloudstack/alibabacloudstack/errmsgs"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/mitchellh/go-homedir"
)
func resourceAlibabacloudStackOssBucketObject() *schema.Resource {
resource := &schema.Resource{
Schema: map[string]*schema.Schema{
"bucket": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"key": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"source": {
Type: schema.TypeString,
Optional: true,
ConflictsWith: []string{"content"},
},
"content": {
Type: schema.TypeString,
Optional: true,
ConflictsWith: []string{"source"},
},
"acl": {
Type: schema.TypeString,
Default: oss.ACLPrivate,
Optional: true,
ValidateFunc: validation.StringInSlice([]string{"private", "public-read", "public-read-write"}, false),
},
"content_type": {
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"cache_control": {
Type: schema.TypeString,
Optional: true,
},
"content_disposition": {
Type: schema.TypeString,
Optional: true,
},
"content_encoding": {
Type: schema.TypeString,
Optional: true,
},
"content_md5": {
Type: schema.TypeString,
Optional: true,
},
"expires": {
Type: schema.TypeString,
Optional: true,
},
"server_side_encryption": {
Type: schema.TypeString,
Optional: true,
ValidateFunc: validation.StringInSlice([]string{string(ServerSideEncryptionKMS), string(ServerSideEncryptionAes256)}, false),
Default: ServerSideEncryptionAes256,
},
"kms_key_id": {
Type: schema.TypeString,
Optional: true,
DiffSuppressFunc: func(k, old, new string, d *schema.ResourceData) bool {
return ServerSideEncryptionKMS != d.Get("server_side_encryption").(string)
},
},
"version_id": {
Type: schema.TypeString,
Computed: true,
},
},
}
setResourceFunc(resource, resourceAlibabacloudStackOssBucketObjectCreate,
resourceAlibabacloudStackOssBucketObjectRead,
resourceAlibabacloudStackOssBucketObjectUpdate,
resourceAlibabacloudStackOssBucketObjectDelete)
return resource
}
func resourceAlibabacloudStackOssBucketObjectCreate(d *schema.ResourceData, meta interface{}) error {
return nil
}
func resourceAlibabacloudStackOssBucketObjectUpdate(d *schema.ResourceData, meta interface{}) error {
return resourceAlibabacloudStackOssBucketObjectPut(d, meta)
}
func resourceAlibabacloudStackOssBucketObjectPut(d *schema.ResourceData, meta interface{}) error {
client := meta.(*connectivity.AlibabacloudStackClient)
var requestInfo *oss.Client
bucketName := d.Get("bucket").(string)
raw, err := client.WithOssDataClient(func(ossClient *oss.Client) (interface{}, error) {
requestInfo = ossClient
return ossClient.Bucket(bucketName)
})
if err != nil {
errmsg := ""
return errmsgs.WrapErrorf(err, errmsgs.RequestV1ErrorMsg, "alibabacloudstack_oss_bucket_object", "Bucket", errmsgs.AlibabacloudStackLogGoSdkERROR, errmsg)
}
addDebug("Bucket", raw, requestInfo, map[string]string{"bucketName": bucketName})
bucket, _ := raw.(*oss.Bucket)
var filePath string
var body io.Reader
if v, ok := d.GetOk("source"); ok {
source := v.(string)
path, err := homedir.Expand(source)
if err != nil {
return errmsgs.WrapError(err)
}
filePath = path
} else if v, ok := d.GetOk("content"); ok {
content := v.(string)
body = bytes.NewReader([]byte(content))
} else {
return errmsgs.WrapError(errmsgs.Error("[ERROR] Must specify \"source\" or \"content\" field"))
}
key := d.Get("key").(string)
options, err := buildObjectHeaderOptions(d)
if v, ok := d.GetOk("server_side_encryption"); ok {
options = append(options, oss.ServerSideEncryption(v.(string)))
}
if v, ok := d.GetOk("kms_key_id"); ok {
options = append(options, oss.ServerSideEncryptionKeyID(v.(string)))
}
if err != nil {
return errmsgs.WrapError(err)
}
if filePath != "" {
err = bucket.PutObjectFromFile(key, filePath, options...)
}
if body != nil {
err = bucket.PutObject(key, body, options...)
}
if err != nil {
return errmsgs.WrapError(errmsgs.Error("Error putting object in Oss bucket (%#v): %s", bucket, err))
}
d.SetId(fmt.Sprintf("%s:%s", bucketName, key))
return nil
}
func resourceAlibabacloudStackOssBucketObjectRead(d *schema.ResourceData, meta interface{}) error {
client := meta.(*connectivity.AlibabacloudStackClient)
var requestInfo *oss.Client
var bucketName, key string
if id_info := strings.SplitN(d.Id(), ":", 2) ; len(id_info) == 1 {
// 兼容老的Id d.SetId(key)
bucketName = d.Get("bucket").(string)
key = d.Get("key").(string)
d.SetId(fmt.Sprintf("%s:%s", bucketName, key))
}else {
bucketName = id_info[0]
key = id_info[1]
}
raw, err := client.WithOssDataClient(func(ossClient *oss.Client) (interface{}, error) {
requestInfo = ossClient
return ossClient.Bucket(bucketName)
})
if err != nil {
errmsg := ""
return errmsgs.WrapErrorf(err, errmsgs.RequestV1ErrorMsg, d.Id(), "Bucket", errmsgs.AlibabacloudStackLogGoSdkERROR, errmsg)
}
addDebug("Bucket", raw, requestInfo, map[string]string{"bucketName": bucketName})
bucket, _ := raw.(*oss.Bucket)
options, err := buildObjectHeaderOptions(d)
if err != nil {
return errmsgs.WrapError(err)
}
object, err := bucket.GetObjectDetailedMeta(key, options...)
if err != nil {
if errmsgs.IsExpectedErrors(err, []string{"404 Not Found"}) {
d.SetId("")
return errmsgs.WrapError(errmsgs.Error("To get the Object: %#v but it is not exist in the specified bucket %s.", key, bucketName))
}
return errmsgs.WrapErrorf(err, errmsgs.DefaultErrorMsg, d.Id(), "GetObjectDetailedMeta", errmsgs.AlibabacloudStackLogGoSdkERROR)
}
addDebug("GetObjectDetailedMeta", object, requestInfo, map[string]interface{}{
"objectKey": key,
"options": options,
})
if acl, err := bucket.GetObjectACL(key, options...); err == nil {
// 需要特殊权限,可能会失败,失败时暂时不覆盖该属性
d.Set("acl", acl.ACL)
}
d.Set("bucket", bucketName)
d.Set("key", key)
d.Set("content_type", object.Get("Content-Type"))
//d.Set("cache_control", object.Get("Cache-Control"))
d.Set("server_side_encryption", object.Get("X-Oss-Server-Side-Encryption"))
d.Set("content_disposition", object.Get("Content-Disposition"))
d.Set("content_encoding", object.Get("Content-Encoding"))
d.Set("expires", object.Get("Expires"))
d.Set("version_id", object.Get("x-oss-version-id"))
return nil
}
func resourceAlibabacloudStackOssBucketObjectDelete(d *schema.ResourceData, meta interface{}) error {
client := meta.(*connectivity.AlibabacloudStackClient)
ossService := OssService{client}
var requestInfo *oss.Client
raw, err := client.WithOssDataClient(func(ossClient *oss.Client) (interface{}, error) {
requestInfo = ossClient
return ossClient.Bucket(d.Get("bucket").(string))
})
if err != nil {
errmsg := ""
return errmsgs.WrapErrorf(err, errmsgs.RequestV1ErrorMsg, d.Id(), "Bucket", errmsgs.AlibabacloudStackLogGoSdkERROR, errmsg)
}
addDebug("Bucket", raw, requestInfo, map[string]string{"bucketName": d.Get("bucket").(string)})
bucket, _ := raw.(*oss.Bucket)
err = bucket.DeleteObject(d.Get("key").(string))
if err != nil {
if errmsgs.IsExpectedErrors(err, []string{"No Content", "Not Found"}) {
return nil
}
return errmsgs.WrapErrorf(err, errmsgs.DefaultErrorMsg, d.Id(), "DeleteObject", errmsgs.AlibabacloudStackLogGoSdkERROR)
}
return errmsgs.WrapError(ossService.WaitForOssBucketObject(bucket, d.Id(), Deleted, DefaultTimeoutMedium))
}
func buildObjectHeaderOptions(d *schema.ResourceData) (options []oss.Option, err error) {
if v, ok := d.GetOk("acl"); ok {
options = append(options, oss.ObjectACL(oss.ACLType(v.(string))))
}
if v, ok := d.GetOk("content_type"); ok {
options = append(options, oss.ContentType(v.(string)))
}
if v, ok := d.GetOk("cache_control"); ok {
options = append(options, oss.CacheControl(v.(string)))
}
if v, ok := d.GetOk("content_disposition"); ok {
options = append(options, oss.ContentDisposition(v.(string)))
}
if v, ok := d.GetOk("content_encoding"); ok {
options = append(options, oss.ContentEncoding(v.(string)))
}
if v, ok := d.GetOk("content_md5"); ok {
options = append(options, oss.ContentMD5(v.(string)))
}
if v, ok := d.GetOk("expires"); ok {
expires := v.(string)
expiresTime, err := time.Parse(time.RFC1123, expires)
if err != nil {
return nil, fmt.Errorf("expires format must respect the RFC1123 standard (current value: %s)", expires)
}
options = append(options, oss.Expires(expiresTime))
}
if options == nil || len(options) == 0 {
log.Printf("[WARN] Object header options is nil.")
}
return options, nil
}