diff --git a/huaweicloud/data_source_huaweicloud_obs_bucket_object.go b/huaweicloud/data_source_huaweicloud_obs_bucket_object.go new file mode 100644 index 0000000000..73a388a330 --- /dev/null +++ b/huaweicloud/data_source_huaweicloud_obs_bucket_object.go @@ -0,0 +1,119 @@ +package huaweicloud + +import ( + "fmt" + "log" + "strings" + + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + "github.com/huaweicloud/golangsdk/openstack/obs" +) + +func dataSourceObsBucketObject() *schema.Resource { + return &schema.Resource{ + Read: dataSourceObsBucketObjectRead, + + Schema: map[string]*schema.Schema{ + "bucket": { + Type: schema.TypeString, + Required: true, + }, + + "key": { + Type: schema.TypeString, + Required: true, + }, + + "storage_class": { + Type: schema.TypeString, + Computed: true, + }, + + "content_type": { + Type: schema.TypeString, + Computed: true, + }, + + "etag": { + Type: schema.TypeString, + Computed: true, + }, + + "version_id": { + Type: schema.TypeString, + Computed: true, + }, + + "size": { + Type: schema.TypeInt, + Computed: true, + }, + }, + } +} + +// Attribute parameters are not returned in one interface. +// Two interfaces need to be called to get all parameters. +func dataSourceObsBucketObjectRead(d *schema.ResourceData, meta interface{}) error { + config := meta.(*Config) + obsClient, err := config.newObjectStorageClient(GetRegion(d, config)) + if err != nil { + return fmt.Errorf("Error creating HuaweiCloud OBS client: %s", err) + } + + bucket := d.Get("bucket").(string) + key := d.Get("key").(string) + + objects, err := obsClient.ListObjects(&obs.ListObjectsInput{ + Bucket: bucket, + ListObjsInput: obs.ListObjsInput{ + Prefix: key, + }, + }) + if err != nil { + return getObsError("Error listing objects of OBS bucket", bucket, err) + } + + var exist bool + var objectContent obs.Content + for _, content := range objects.Contents { + if key == content.Key { + exist = true + objectContent = content + break + } + } + if !exist { + d.SetId("") + return fmt.Errorf("object %s not found in bucket %s", key, bucket) + } + + log.Printf("[DEBUG] Data Source Reading OBS Bucket Object %s: %#v", key, objectContent) + + object, err := obsClient.GetObject(&obs.GetObjectInput{ + GetObjectMetadataInput: obs.GetObjectMetadataInput{ + Bucket: bucket, + Key: key, + }, + }) + if err != nil { + return getObsError("Error get object info of OBS bucket", bucket, err) + } + + log.Printf("[DEBUG] Data Source Reading OBS Bucket Object : %#v", object) + + d.SetId(key) + d.Set("size", objectContent.Size) + d.Set("etag", strings.Trim(objectContent.ETag, `"`)) + d.Set("version_id", object.VersionId) + d.Set("content_type", object.ContentType) + + class := string(objectContent.StorageClass) + if class == "" { + d.Set("storage_class", "STANDARD") + } else { + d.Set("storage_class", normalizeStorageClass(class)) + } + + return nil +} diff --git a/huaweicloud/data_source_huaweicloud_obs_bucket_object_test.go b/huaweicloud/data_source_huaweicloud_obs_bucket_object_test.go new file mode 100644 index 0000000000..d69bdfe93e --- /dev/null +++ b/huaweicloud/data_source_huaweicloud_obs_bucket_object_test.go @@ -0,0 +1,226 @@ +package huaweicloud + +import ( + "fmt" + "io/ioutil" + "os" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/helper/acctest" + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/terraform" + "github.com/huaweicloud/golangsdk/openstack/obs" +) + +func TestAccHuaweiCloudObsBucketObjectDataSource_content(t *testing.T) { + rInt := acctest.RandInt() + resourceConf, dataSourceConf := testAccHuaweiCloudObsBucketObjectDataSource_content(rInt) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheckS3(t) }, + Providers: testAccProviders, + PreventPostDestroyRefresh: true, + Steps: []resource.TestStep{ + { + Config: resourceConf, + Check: resource.ComposeTestCheckFunc( + testAccCheckObsBucketObjectExists("huaweicloud_obs_bucket_object.object"), + ), + }, + { + Config: dataSourceConf, + Check: resource.ComposeTestCheckFunc( + testAccCheckAwsObsObjectDataSourceExists("data.huaweicloud_obs_bucket_object.obj"), + resource.TestCheckResourceAttr("data.huaweicloud_obs_bucket_object.obj", "content_type", "binary/octet-stream"), + resource.TestCheckResourceAttr("data.huaweicloud_obs_bucket_object.obj", "storage_class", "STANDARD"), + ), + }, + }, + }) +} + +func TestAccHuaweiCloudObsBucketObjectDataSource_source(t *testing.T) { + tmpFile, err := ioutil.TempFile("", "tf-acc-obs-obj-source") + if err != nil { + t.Fatal(err) + } + defer os.Remove(tmpFile.Name()) + + rInt := acctest.RandInt() + + // write test data to the tempfile + for i := 0; i < 1024; i++ { + _, err := tmpFile.WriteString("test obs object file storage") + if err != nil { + t.Fatal(err) + } + } + tmpFile.Close() + + resourceConf, dataSourceConf := testAccHuaweiCloudObsBucketObjectDataSource_source(rInt, tmpFile.Name()) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheckS3(t) }, + Providers: testAccProviders, + PreventPostDestroyRefresh: true, + Steps: []resource.TestStep{ + { + Config: resourceConf, + Check: resource.ComposeTestCheckFunc( + testAccCheckObsBucketObjectExists("huaweicloud_obs_bucket_object.object"), + ), + }, + { + Config: dataSourceConf, + Check: resource.ComposeTestCheckFunc( + testAccCheckAwsObsObjectDataSourceExists("data.huaweicloud_obs_bucket_object.obj"), + resource.TestCheckResourceAttr("data.huaweicloud_obs_bucket_object.obj", "content_type", "binary/octet-stream"), + resource.TestCheckResourceAttr("data.huaweicloud_obs_bucket_object.obj", "storage_class", "STANDARD"), + ), + }, + }, + }) +} + +func TestAccHuaweiCloudObsBucketObjectDataSource_allParams(t *testing.T) { + rInt := acctest.RandInt() + resourceConf, dataSourceConf := testAccHuaweiCloudObsBucketObjectDataSource_allParams(rInt) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheckS3(t) }, + Providers: testAccProviders, + PreventPostDestroyRefresh: true, + Steps: []resource.TestStep{ + { + Config: resourceConf, + Check: resource.ComposeTestCheckFunc( + testAccCheckObsBucketObjectExists("huaweicloud_obs_bucket_object.object"), + ), + }, + { + Config: dataSourceConf, + Check: resource.ComposeTestCheckFunc( + testAccCheckAwsObsObjectDataSourceExists("data.huaweicloud_obs_bucket_object.obj"), + resource.TestCheckResourceAttr("data.huaweicloud_obs_bucket_object.obj", "content_type", "application/unknown"), + resource.TestCheckResourceAttr("data.huaweicloud_obs_bucket_object.obj", "storage_class", "STANDARD"), + resource.TestCheckResourceAttr("data.huaweicloud_obs_bucket_object.obj", "body", "\t{\"msg\": \"Hi there!\"}\n"), + ), + }, + }, + }) +} + +func testAccCheckAwsObsObjectDataSourceExists(n string) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[n] + if !ok { + return fmt.Errorf("Can't find Obs object data source: %s", n) + } + + if rs.Primary.ID == "" { + return fmt.Errorf("Obs object data source ID not set") + } + + bucket := rs.Primary.Attributes["bucket"] + key := rs.Primary.Attributes["key"] + + config := testAccProvider.Meta().(*Config) + obsClient, err := config.newObjectStorageClient(OS_REGION_NAME) + if err != nil { + return fmt.Errorf("Error creating HuaweiCloud OBS client: %s", err) + } + + respList, err := obsClient.ListObjects(&obs.ListObjectsInput{ + Bucket: bucket, + ListObjsInput: obs.ListObjsInput{ + Prefix: key, + }, + }) + if err != nil { + return getObsError("Error listing objects of OBS bucket", bucket, err) + } + + var exist bool + for _, content := range respList.Contents { + if key == content.Key { + exist = true + break + } + } + if !exist { + return fmt.Errorf("object %s not found in bucket %s", key, bucket) + } + + return nil + } +} + +func testAccHuaweiCloudObsBucketObjectDataSource_content(randInt int) (string, string) { + resource := fmt.Sprintf(` +resource "huaweicloud_obs_bucket" "object_bucket" { + bucket = "tf-object-test-bucket-%d" +} +resource "huaweicloud_obs_bucket_object" "object" { + bucket = huaweicloud_obs_bucket.object_bucket.bucket + key = "test-key-%d" + content = "some_bucket_content" +} +`, randInt, randInt) + + dataSource := fmt.Sprintf(`%s +data "huaweicloud_obs_bucket_object" "obj" { + bucket = "tf-object-test-bucket-%d" + key = "test-key-%d" +}`, resource, randInt, randInt) + + return resource, dataSource +} + +func testAccHuaweiCloudObsBucketObjectDataSource_source(randInt int, source string) (string, string) { + resource := fmt.Sprintf(` +resource "huaweicloud_obs_bucket" "object_bucket" { + bucket = "tf-object-test-bucket-%d" +} +resource "huaweicloud_obs_bucket_object" "object" { + bucket = huaweicloud_obs_bucket.object_bucket.bucket + key = "test-key-%d" + source = "%s" + content_type = "binary/octet-stream" +} +`, randInt, randInt, source) + + dataSource := fmt.Sprintf(`%s +data "huaweicloud_obs_bucket_object" "obj" { + bucket = "tf-object-test-bucket-%d" + key = "test-key-%d" +}`, resource, randInt, randInt) + + return resource, dataSource +} + +func testAccHuaweiCloudObsBucketObjectDataSource_allParams(randInt int) (string, string) { + resource := fmt.Sprintf(` +resource "huaweicloud_obs_bucket" "object_bucket" { + bucket = "tf-object-test-bucket-%d" +} +resource "huaweicloud_obs_bucket_object" "object" { + bucket = huaweicloud_obs_bucket.object_bucket.bucket + key = "test-key-%d" + content = < Object Storage Service (OBS)