alicloud/resource_alicloud_oss_bucket_object.go (244 lines of code) (raw):
package alicloud
import (
"bytes"
"fmt"
"io"
"log"
"strings"
"time"
"github.com/hashicorp/terraform-plugin-sdk/helper/validation"
"github.com/aliyun/aliyun-oss-go-sdk/oss"
"github.com/aliyun/terraform-provider-alicloud/alicloud/connectivity"
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
"github.com/mitchellh/go-homedir"
)
func resourceAlicloudOssBucketObject() *schema.Resource {
return &schema.Resource{
Create: resourceAlicloudOssBucketObjectPut,
Read: resourceAlicloudOssBucketObjectRead,
Update: resourceAlicloudOssBucketObjectPut,
Delete: resourceAlicloudOssBucketObjectDelete,
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,
},
"content_length": {
Type: schema.TypeString,
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)
},
},
"etag": {
Type: schema.TypeString,
Computed: true,
},
"version_id": {
Type: schema.TypeString,
Computed: true,
},
},
}
}
func resourceAlicloudOssBucketObjectPut(d *schema.ResourceData, meta interface{}) error {
client := meta.(*connectivity.AliyunClient)
var requestInfo *oss.Client
raw, err := client.WithOssClient(func(ossClient *oss.Client) (interface{}, error) {
requestInfo = ossClient
return ossClient.Bucket(d.Get("bucket").(string))
})
if err != nil {
return WrapErrorf(err, DefaultErrorMsg, "alicloud_oss_bucket_object", "Bucket", AliyunOssGoSdk)
}
addDebug("Bucket", raw, requestInfo, map[string]string{"bucketName": d.Get("bucket").(string)})
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 WrapError(err)
}
filePath = path
} else if v, ok := d.GetOk("content"); ok {
content := v.(string)
body = bytes.NewReader([]byte(content))
} else {
return WrapError(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 WrapError(err)
}
if filePath != "" {
err = bucket.PutObjectFromFile(key, filePath, options...)
}
if body != nil {
err = bucket.PutObject(key, body, options...)
}
if err != nil {
return WrapError(Error("Error putting object in Oss bucket (%#v): %s", bucket, err))
}
d.SetId(key)
return resourceAlicloudOssBucketObjectRead(d, meta)
}
func resourceAlicloudOssBucketObjectRead(d *schema.ResourceData, meta interface{}) error {
client := meta.(*connectivity.AliyunClient)
var requestInfo *oss.Client
raw, err := client.WithOssClient(func(ossClient *oss.Client) (interface{}, error) {
requestInfo = ossClient
return ossClient.Bucket(d.Get("bucket").(string))
})
if err != nil {
return WrapErrorf(err, DefaultErrorMsg, d.Id(), "Bucket", AliyunOssGoSdk)
}
addDebug("Bucket", raw, requestInfo, map[string]string{"bucketName": d.Get("bucket").(string)})
bucket, _ := raw.(*oss.Bucket)
options, err := buildObjectHeaderOptions(d)
if err != nil {
return WrapError(err)
}
object, err := bucket.GetObjectDetailedMeta(d.Get("key").(string), options...)
if err != nil {
if IsExpectedErrors(err, []string{"404 Not Found", "NoSuchKey"}) {
d.SetId("")
return WrapError(Error("To get the Object: %#v but it is not exist in the specified bucket %s.", d.Get("key").(string), d.Get("bucket").(string)))
}
return WrapErrorf(err, DefaultErrorMsg, d.Id(), "GetObjectDetailedMeta", AliyunOssGoSdk)
}
addDebug("GetObjectDetailedMeta", object, requestInfo, map[string]interface{}{
"objectKey": d.Get("key").(string),
"options": options,
})
d.Set("content_type", object.Get("Content-Type"))
d.Set("content_length", object.Get("Content-Length"))
d.Set("cache_control", object.Get("Cache-Control"))
d.Set("content_disposition", object.Get("Content-Disposition"))
d.Set("content_encoding", object.Get("Content-Encoding"))
d.Set("expires", object.Get("Expires"))
d.Set("etag", strings.Trim(object.Get("ETag"), `"`))
d.Set("version_id", object.Get("x-oss-version-id"))
return nil
}
func resourceAlicloudOssBucketObjectDelete(d *schema.ResourceData, meta interface{}) error {
client := meta.(*connectivity.AliyunClient)
ossService := OssService{client}
var requestInfo *oss.Client
raw, err := client.WithOssClient(func(ossClient *oss.Client) (interface{}, error) {
requestInfo = ossClient
return ossClient.Bucket(d.Get("bucket").(string))
})
if err != nil {
return WrapErrorf(err, DefaultErrorMsg, d.Id(), "Bucket", AliyunOssGoSdk)
}
addDebug("Bucket", raw, requestInfo, map[string]string{"bucketName": d.Get("bucket").(string)})
bucket, _ := raw.(*oss.Bucket)
err = bucket.DeleteObject(d.Id())
if err != nil {
if IsExpectedErrors(err, []string{"No Content", "Not Found"}) {
return nil
}
return WrapErrorf(err, DefaultErrorMsg, d.Id(), "DeleteObject", AliyunOssGoSdk)
}
return 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
}