diff --git a/docs/data-sources/cts_check_bucket.md b/docs/data-sources/cts_check_bucket.md
new file mode 100644
index 00000000000..1a35f85e060
--- /dev/null
+++ b/docs/data-sources/cts_check_bucket.md
@@ -0,0 +1,70 @@
+---
+subcategory: "Cloud Trace Service (CTS)"
+layout: "huaweicloud"
+page_title: "HuaweiCloud: huaweicloud_cts_check_bucket"
+description: |-
+ Use this data source to check whether data can be transferred to the OBS bucket.
+---
+
+# huaweicloud_cts_check_bucket
+
+Use this data source to check whether data can be transferred to the OBS bucket.
+
+## Example Usage
+
+```hcl
+data "huaweicloud_cts_check_bucket" "test" {
+ bucket_name = "my_bucket"
+ bucket_location = "cn-north-4"
+}
+```
+
+## Argument Reference
+
+The following arguments are supported:
+
+* `region` - (Optional, String) Specifies the region in which to query the resource.
+ If omitted, the provider-level region will be used.
+
+* `bucket_name` - (Required, String) Specifies the OBS bucket name.
+
+* `bucket_location` - (Required, String) Specifies the OBS bucket location.
+
+* `is_support_trace_files_encryption` - (Optional, Bool) Specifies whether trace files are encrypted during transfer to
+ an OBS bucket.
+
+* `kms_id` - (Optional, String) Specifies the Key ID used for encrypting transferred trace files.
+
+## Attribute Reference
+
+In addition to all arguments above, the following attributes are exported:
+
+* `id` - The data source ID.
+
+* `buckets` - The OBS bucket information.
+ The [buckets](#BucketsAttr) structure is documented below.
+
+
+The `buckets` block supports:
+
+* `bucket_name` - The OBS bucket name.
+
+* `bucket_location` - The OBS bucket location.
+
+* `is_support_trace_files_encryption` - Whether trace files are encrypted during transfer to an OBS bucket.
+
+* `kms_id` - The Key ID used for encrypting transferred trace files.
+
+* `check_bucket_response` - The check result of the OBS bucket.
+ The [check_bucket_response](#CheckBucketResponse) structure is documented below.
+
+
+The `check_bucket_response` block supports:
+
+* `error_code` - The error code.
+
+* `error_message` - The error message.
+
+* `response_code` - The returned HTTP status code.
+
+* `success` - Whether the transfer is successful.
diff --git a/huaweicloud/provider.go b/huaweicloud/provider.go
index 4637616f4fb..29fa845300b 100644
--- a/huaweicloud/provider.go
+++ b/huaweicloud/provider.go
@@ -628,6 +628,7 @@ func Provider() *schema.Provider {
"huaweicloud_codearts_inspector_host_groups": codeartsinspector.DataSourceCodeartsInspectorHostGroups(),
"huaweicloud_codearts_inspector_hosts": codeartsinspector.DataSourceCodeartsInspectorHosts(),
+ "huaweicloud_cts_check_bucket": cts.DataSourceCheckBucket(),
"huaweicloud_cts_notifications": cts.DataSourceNotifications(),
"huaweicloud_cts_traces": cts.DataSourceCtsTraces(),
"huaweicloud_cts_trackers": cts.DataSourceCtsTrackers(),
diff --git a/huaweicloud/services/acceptance/acceptance.go b/huaweicloud/services/acceptance/acceptance.go
index d712972c94e..aa0d97e49c6 100644
--- a/huaweicloud/services/acceptance/acceptance.go
+++ b/huaweicloud/services/acceptance/acceptance.go
@@ -300,6 +300,7 @@ var (
HW_CFW_PREDEFINED_ADDRESS_GROUP2 = os.Getenv("HW_CFW_PREDEFINED_ADDRESS_GROUP2")
HW_CFW_IPS_CUSTOM_RULE = os.Getenv("HW_CFW_IPS_CUSTOM_RULE")
+ HW_CTS_KMS_ID = os.Getenv("HW_CTS_KMS_ID")
HW_CTS_START_TIME = os.Getenv("HW_CTS_START_TIME")
HW_CTS_END_TIME = os.Getenv("HW_CTS_END_TIME")
@@ -1569,6 +1570,13 @@ func TestAccPreCheckCCConnectionRouteRegionName(t *testing.T) {
}
}
+// lintignore:AT003
+func TestAccPreCheckCtsKmsId(t *testing.T) {
+ if HW_CTS_KMS_ID == "" {
+ t.Skip("HW_CTS_KMS_ID must be set for CTS acceptance tests")
+ }
+}
+
// lintignore:AT003
func TestAccPreCheckCtsTimeRange(t *testing.T) {
if HW_CTS_START_TIME == "" || HW_CTS_END_TIME == "" {
diff --git a/huaweicloud/services/acceptance/cts/data_source_huaweicloud_cts_check_bucket_test.go b/huaweicloud/services/acceptance/cts/data_source_huaweicloud_cts_check_bucket_test.go
new file mode 100644
index 00000000000..a414c3708dc
--- /dev/null
+++ b/huaweicloud/services/acceptance/cts/data_source_huaweicloud_cts_check_bucket_test.go
@@ -0,0 +1,81 @@
+package cts
+
+import (
+ "fmt"
+ "testing"
+
+ "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
+
+ "github.com/huaweicloud/terraform-provider-huaweicloud/huaweicloud/services/acceptance"
+)
+
+func TestAccDataSourceCheckBucket_basic(t *testing.T) {
+ dataSource := "data.huaweicloud_cts_check_bucket.test"
+ rName := acceptance.RandomAccResourceNameWithDash()
+ dc := acceptance.InitDataSourceCheck(dataSource)
+ baseConfig := testDataSourceCheckBucket_base(rName)
+
+ resource.ParallelTest(t, resource.TestCase{
+ PreCheck: func() {
+ acceptance.TestAccPreCheck(t)
+ acceptance.TestAccPreCheckCtsKmsId(t)
+ },
+ ProviderFactories: acceptance.TestAccProviderFactories,
+ Steps: []resource.TestStep{
+ {
+ Config: testDataSourceCheckBucket_basic(baseConfig),
+ Check: resource.ComposeTestCheckFunc(
+ dc.CheckResourceExists(),
+ resource.TestCheckResourceAttr(dataSource, "buckets.0.bucket_name", rName),
+ resource.TestCheckResourceAttr(dataSource, "buckets.0.check_bucket_response.0.response_code", "200"),
+ resource.TestCheckResourceAttr(dataSource, "buckets.0.check_bucket_response.0.success", "true"),
+ ),
+ },
+ {
+ Config: testDataSourceCheckBucket_KmsId(baseConfig),
+ Check: resource.ComposeTestCheckFunc(
+ dc.CheckResourceExists(),
+ resource.TestCheckResourceAttr(dataSource, "buckets.0.bucket_name", rName),
+ resource.TestCheckResourceAttr(dataSource, "buckets.0.check_bucket_response.0.response_code", "200"),
+ resource.TestCheckResourceAttr(dataSource, "buckets.0.check_bucket_response.0.success", "true"),
+ resource.TestCheckResourceAttr(dataSource, "buckets.0.is_support_trace_files_encryption", "true"),
+ resource.TestCheckResourceAttr(dataSource, "buckets.0.kms_id", acceptance.HW_CTS_KMS_ID),
+ ),
+ },
+ },
+ })
+}
+
+func testDataSourceCheckBucket_basic(config string) string {
+ return fmt.Sprintf(`
+%s
+
+data "huaweicloud_cts_check_bucket" "test" {
+ bucket_name = huaweicloud_obs_bucket.bucket.bucket
+ bucket_location = huaweicloud_obs_bucket.bucket.region
+}
+`, config)
+}
+
+func testDataSourceCheckBucket_KmsId(config string) string {
+ return fmt.Sprintf(`
+%[1]s
+
+data "huaweicloud_cts_check_bucket" "test" {
+ bucket_name = huaweicloud_obs_bucket.bucket.bucket
+ bucket_location = huaweicloud_obs_bucket.bucket.region
+ kms_id = "%[2]s"
+ is_support_trace_files_encryption = true
+}
+`, config, acceptance.HW_CTS_KMS_ID)
+}
+
+func testDataSourceCheckBucket_base(rName string) string {
+ return fmt.Sprintf(`
+resource "huaweicloud_obs_bucket" "bucket" {
+ bucket = "%s"
+ acl = "public-read"
+ force_destroy = true
+}
+`, rName)
+}
diff --git a/huaweicloud/services/cts/data_source_huaweicloud_cts_check_bucket.go b/huaweicloud/services/cts/data_source_huaweicloud_cts_check_bucket.go
new file mode 100644
index 00000000000..774916e4fb6
--- /dev/null
+++ b/huaweicloud/services/cts/data_source_huaweicloud_cts_check_bucket.go
@@ -0,0 +1,198 @@
+package cts
+
+import (
+ "context"
+ "strings"
+
+ "github.com/hashicorp/go-multierror"
+ "github.com/hashicorp/go-uuid"
+ "github.com/hashicorp/terraform-plugin-sdk/v2/diag"
+ "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
+ "github.com/tidwall/gjson"
+
+ "github.com/huaweicloud/terraform-provider-huaweicloud/huaweicloud/config"
+ "github.com/huaweicloud/terraform-provider-huaweicloud/huaweicloud/helper/httphelper"
+ "github.com/huaweicloud/terraform-provider-huaweicloud/huaweicloud/helper/schemas"
+ "github.com/huaweicloud/terraform-provider-huaweicloud/huaweicloud/utils"
+)
+
+func DataSourceCheckBucket() *schema.Resource {
+ return &schema.Resource{
+ ReadContext: dataSourceCtsCheckBucketRead,
+
+ Schema: map[string]*schema.Schema{
+ "region": {
+ Type: schema.TypeString,
+ Optional: true,
+ Computed: true,
+ Description: `Specifies the region in which to query the resource. If omitted, the provider-level region will be used.`,
+ },
+ "bucket_name": {
+ Type: schema.TypeString,
+ Required: true,
+ Description: `Specifies the OBS bucket name.`,
+ },
+ "bucket_location": {
+ Type: schema.TypeString,
+ Required: true,
+ Description: `Specifies the OBS bucket location.`,
+ },
+ "kms_id": {
+ Type: schema.TypeString,
+ Optional: true,
+ Description: `Specifies the Key ID used for encrypting transferred trace files.`,
+ },
+ "is_support_trace_files_encryption": {
+ Type: schema.TypeBool,
+ Optional: true,
+ Description: `Specifies whether trace files are encrypted during transfer to an OBS bucket.`,
+ },
+ "buckets": {
+ Type: schema.TypeList,
+ Computed: true,
+ Description: `The OBS bucket information.`,
+ Elem: &schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "bucket_name": {
+ Type: schema.TypeString,
+ Computed: true,
+ Description: `The OBS bucket name.`,
+ },
+ "bucket_location": {
+ Type: schema.TypeString,
+ Computed: true,
+ Description: `The OBS bucket location.`,
+ },
+ "kms_id": {
+ Type: schema.TypeString,
+ Computed: true,
+ Description: `The Key ID used for encrypting transferred trace files.`,
+ },
+ "is_support_trace_files_encryption": {
+ Type: schema.TypeBool,
+ Computed: true,
+ Description: `Whether trace files are encrypted during transfer to an OBS bucket.`,
+ },
+ "check_bucket_response": {
+ Type: schema.TypeList,
+ Computed: true,
+ Description: `The check result of the OBS bucket.`,
+ Elem: &schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "error_code": {
+ Type: schema.TypeString,
+ Computed: true,
+ Description: `The error code.`,
+ },
+ "error_message": {
+ Type: schema.TypeString,
+ Computed: true,
+ Description: `The error message.`,
+ },
+ "response_code": {
+ Type: schema.TypeInt,
+ Computed: true,
+ Description: `The returned HTTP status code.`,
+ },
+ "success": {
+ Type: schema.TypeBool,
+ Computed: true,
+ Description: `Whether the transfer is successful.`,
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ }
+}
+
+type CheckBucketDSWrapper struct {
+ *schemas.ResourceDataWrapper
+ Config *config.Config
+}
+
+func newCheckBucketDSWrapper(d *schema.ResourceData, meta interface{}) *CheckBucketDSWrapper {
+ return &CheckBucketDSWrapper{
+ ResourceDataWrapper: schemas.NewSchemaWrapper(d),
+ Config: meta.(*config.Config),
+ }
+}
+
+func dataSourceCtsCheckBucketRead(_ context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
+ wrapper := newCheckBucketDSWrapper(d, meta)
+ checkObsBucketsRst, err := wrapper.CheckObsBuckets()
+ if err != nil {
+ return diag.FromErr(err)
+ }
+
+ id, err := uuid.GenerateUUID()
+ if err != nil {
+ return diag.FromErr(err)
+ }
+ d.SetId(id)
+
+ err = wrapper.checkObsBucketsToSchema(checkObsBucketsRst)
+ if err != nil {
+ return diag.FromErr(err)
+ }
+
+ return nil
+}
+
+// @API CTS POST /v3/{domain_id}/checkbucket
+func (w *CheckBucketDSWrapper) CheckObsBuckets() (*gjson.Result, error) {
+ client, err := w.NewClient(w.Config, "cts")
+ if err != nil {
+ return nil, err
+ }
+
+ uri := "/v3/{domain_id}/checkbucket"
+ uri = strings.ReplaceAll(uri, "{domain_id}", w.Config.DomainID)
+ params := map[string]any{
+ "bucket_location": w.Get("bucket_location"),
+ "bucket_name": w.Get("bucket_name"),
+ "is_support_trace_files_encryption": w.Get("is_support_trace_files_encryption"),
+ "kms_id": w.Get("kms_id"),
+ }
+ params = utils.RemoveNil(params)
+ reqBody := map[string]any{
+ "buckets": []map[string]any{params},
+ }
+ return httphelper.New(client).
+ Method("POST").
+ URI(uri).
+ Body(reqBody).
+ Request().
+ Result()
+}
+
+func (w *CheckBucketDSWrapper) checkObsBucketsToSchema(body *gjson.Result) error {
+ d := w.ResourceData
+ mErr := multierror.Append(nil,
+ d.Set("region", w.Config.GetRegion(w.ResourceData)),
+ d.Set("buckets", schemas.SliceToList(body.Get("buckets"),
+ func(buckets gjson.Result) any {
+ return map[string]any{
+ "bucket_name": buckets.Get("bucket_name").Value(),
+ "bucket_location": buckets.Get("bucket_location").Value(),
+ "kms_id": buckets.Get("kms_id").Value(),
+ "is_support_trace_files_encryption": buckets.Get("is_support_trace_files_encryption").Value(),
+ "check_bucket_response": schemas.SliceToList(buckets.Get("check_bucket_response"),
+ func(checkBucketResponse gjson.Result) any {
+ return map[string]any{
+ "error_code": checkBucketResponse.Get("error_code").Value(),
+ "error_message": checkBucketResponse.Get("error_message").Value(),
+ "response_code": checkBucketResponse.Get("response_code").Value(),
+ "success": checkBucketResponse.Get("success").Value(),
+ }
+ },
+ ),
+ }
+ },
+ )),
+ )
+ return mErr.ErrorOrNil()
+}