diff --git a/docs/data-sources/rds_pg_sql_limits.md b/docs/data-sources/rds_pg_sql_limits.md new file mode 100644 index 0000000000..0669e3e0bd --- /dev/null +++ b/docs/data-sources/rds_pg_sql_limits.md @@ -0,0 +1,75 @@ +--- +subcategory: "Relational Database Service (RDS)" +layout: "huaweicloud" +page_title: "HuaweiCloud: huaweicloud_rds_pg_sql_limits" +description: |- + Use this data source to get the list of RDS PostgreSQL SQL limits. +--- + +# huaweicloud_rds_pg_sql_limits + +Use this data source to get the list of RDS PostgreSQL SQL limits. + +## Example Usage + +```hcl +variable "instance_id" {} +variable "db_name" {} + +data "huaweicloud_rds_pg_sql_limits" "test" { + instance_id = var.instance_id + db_name = var.db_name +} +``` + +## 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. + +* `instance_id` - (Required, String) Specifies the ID of RDS PostgreSQL instance. + +* `db_name` - (Required, String) Specifies the name of the database. + +* `sql_limit_id` - (Optional, String) Specifies the ID of SQL limit. + +* `query_id` - (Optional, String) Specifies the query ID. + +* `query_string` - (Optional, String) Specifies the text form of SQL statement. + +* `max_concurrency` - (Optional, String) Specifies the number of SQL statements executed simultaneously. + +* `max_waiting` - (Optional, String) Specifies the max waiting time in seconds. + +* `search_path` - (Optional, String) Specifies the query order for names that are not schema qualified. + +* `is_effective` - (Optional, String) Specifies whether the SQL limit is effective. + +## Attribute Reference + +In addition to all arguments above, the following attributes are exported: + +* `id` - The data source ID. + +* `sql_limits` - Indicates the list of SQL limits. + + The [sql_limits](#sql_limits_struct) structure is documented below. + + +The `sql_limits` block supports: + +* `id` - Indicates the ID of SQL limit. + +* `query_id` - Indicates the query ID. + +* `query_string` - Indicates the text form of SQL statement. + +* `max_concurrency` - Indicates the number of SQL statements executed simultaneously. + +* `max_waiting` - Indicates the max waiting time in seconds. + +* `search_path` - Indicates the query order for names that are not schema qualified. + +* `is_effective` - Indicates whether the SQL limit is effective. diff --git a/huaweicloud/provider.go b/huaweicloud/provider.go index 240e06af2e..9019086d5a 100644 --- a/huaweicloud/provider.go +++ b/huaweicloud/provider.go @@ -735,6 +735,7 @@ func Provider() *schema.Provider { "huaweicloud_rds_sql_audit_logs": rds.DataSourceRdsSqlAuditLogs(), "huaweicloud_rds_error_logs": rds.DataSourceRdsErrorLogs(), "huaweicloud_rds_slow_logs": rds.DataSourceRdsSlowLogs(), + "huaweicloud_rds_pg_sql_limits": rds.DataSourceRdsPgSqlLimits(), "huaweicloud_rms_policy_definitions": rms.DataSourcePolicyDefinitions(), "huaweicloud_rms_assignment_package_templates": rms.DataSourceTemplates(), diff --git a/huaweicloud/services/acceptance/rds/data_source_huaweicloud_rds_pg_sql_limits_test.go b/huaweicloud/services/acceptance/rds/data_source_huaweicloud_rds_pg_sql_limits_test.go new file mode 100644 index 0000000000..2bf2d6ae79 --- /dev/null +++ b/huaweicloud/services/acceptance/rds/data_source_huaweicloud_rds_pg_sql_limits_test.go @@ -0,0 +1,202 @@ +package rds + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + + "github.com/huaweicloud/terraform-provider-huaweicloud/huaweicloud/services/acceptance" +) + +func TestAccDataSourceRdsPgSqlLimits_basic(t *testing.T) { + dataSource := "data.huaweicloud_rds_pg_sql_limits.test" + rName := acceptance.RandomAccResourceName() + dc := acceptance.InitDataSourceCheck(dataSource) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { + acceptance.TestAccPreCheck(t) + }, + ProviderFactories: acceptance.TestAccProviderFactories, + Steps: []resource.TestStep{ + { + Config: testDataSourceDataSourceRdsPgSqlLimits_basic(rName), + Check: resource.ComposeTestCheckFunc( + dc.CheckResourceExists(), + resource.TestCheckResourceAttrSet(dataSource, "sql_limits.#"), + resource.TestCheckResourceAttrSet(dataSource, "sql_limits.0.id"), + resource.TestCheckResourceAttrSet(dataSource, "sql_limits.0.query_id"), + resource.TestCheckResourceAttrSet(dataSource, "sql_limits.0.max_concurrency"), + resource.TestCheckResourceAttrSet(dataSource, "sql_limits.0.max_waiting"), + resource.TestCheckResourceAttrSet(dataSource, "sql_limits.0.search_path"), + resource.TestCheckResourceAttrSet(dataSource, "sql_limits.0.is_effective"), + + resource.TestCheckOutput("sql_limit_id_filter_is_useful", "true"), + resource.TestCheckOutput("query_id_filter_is_useful", "true"), + resource.TestCheckOutput("max_concurrency_filter_is_useful", "true"), + resource.TestCheckOutput("max_waiting_filter_is_useful", "true"), + resource.TestCheckOutput("search_path_filter_is_useful", "true"), + resource.TestCheckOutput("is_effective_filter_is_useful", "true"), + resource.TestCheckOutput("query_string_filter_is_useful", "true"), + ), + }, + }, + }) +} + +func testDataSourceDataSourceRdsPgSqlLimits_basic(name string) string { + return fmt.Sprintf(` +%[1]s + +resource "huaweicloud_rds_pg_sql_limit" "test" { + depends_on = [huaweicloud_rds_pg_plugin.test] + + instance_id = huaweicloud_rds_instance.test.id + db_name = "%[2]s" + query_id = "100" + max_concurrency = 20 + max_waiting = 5 + search_path = "public" + switch = "open" + + lifecycle { + ignore_changes = [query_string] + } +} + +resource "huaweicloud_rds_pg_sql_limit" "query_string" { + depends_on = [huaweicloud_rds_pg_plugin.test] + + instance_id = huaweicloud_rds_instance.test.id + db_name = "%[2]s" + query_string = "select" + max_concurrency = 20 + max_waiting = 5 + search_path = "public" + + lifecycle { + ignore_changes = [query_id] + } +} + +data "huaweicloud_rds_pg_sql_limits" "test" { + depends_on = [huaweicloud_rds_pg_sql_limit.test] + + instance_id = huaweicloud_rds_instance.test.id + db_name = "%[2]s" +} + +locals { + sql_limit_id = huaweicloud_rds_pg_sql_limit.test.sql_limit_id +} +data "huaweicloud_rds_pg_sql_limits" "sql_limit_id_filter" { + depends_on = [huaweicloud_rds_pg_sql_limit.test] + + instance_id = huaweicloud_rds_instance.test.id + db_name = "%[2]s" + sql_limit_id = huaweicloud_rds_pg_sql_limit.test.sql_limit_id +} +output "sql_limit_id_filter_is_useful" { + value = length(data.huaweicloud_rds_pg_sql_limits.sql_limit_id_filter.sql_limits) > 0 && alltrue( + [for v in data.huaweicloud_rds_pg_sql_limits.sql_limit_id_filter.sql_limits[*].id : v == local.sql_limit_id] + ) +} + +locals { + query_id = huaweicloud_rds_pg_sql_limit.test.query_id +} +data "huaweicloud_rds_pg_sql_limits" "query_id_filter" { + depends_on = [huaweicloud_rds_pg_sql_limit.test] + + instance_id = huaweicloud_rds_instance.test.id + db_name = "%[2]s" + query_id = huaweicloud_rds_pg_sql_limit.test.query_id +} +output "query_id_filter_is_useful" { + value = length(data.huaweicloud_rds_pg_sql_limits.query_id_filter.sql_limits) > 0 && alltrue( + [for v in data.huaweicloud_rds_pg_sql_limits.query_id_filter.sql_limits[*].query_id : v == local.query_id] + ) +} + +locals { + max_concurrency = huaweicloud_rds_pg_sql_limit.test.max_concurrency +} +data "huaweicloud_rds_pg_sql_limits" "max_concurrency_filter" { + depends_on = [huaweicloud_rds_pg_sql_limit.test] + + instance_id = huaweicloud_rds_instance.test.id + db_name = "%[2]s" + max_concurrency = huaweicloud_rds_pg_sql_limit.test.max_concurrency +} +output "max_concurrency_filter_is_useful" { + value = length(data.huaweicloud_rds_pg_sql_limits.max_concurrency_filter.sql_limits) > 0 && alltrue( + [for v in data.huaweicloud_rds_pg_sql_limits.max_concurrency_filter.sql_limits[*].max_concurrency : v == local.max_concurrency] + ) +} + +locals { + max_waiting = huaweicloud_rds_pg_sql_limit.test.max_waiting +} +data "huaweicloud_rds_pg_sql_limits" "max_waiting_filter" { + depends_on = [huaweicloud_rds_pg_sql_limit.test] + + instance_id = huaweicloud_rds_instance.test.id + db_name = "%[2]s" + max_waiting = huaweicloud_rds_pg_sql_limit.test.max_waiting +} +output "max_waiting_filter_is_useful" { + value = length(data.huaweicloud_rds_pg_sql_limits.max_waiting_filter.sql_limits) > 0 && alltrue( + [for v in data.huaweicloud_rds_pg_sql_limits.max_waiting_filter.sql_limits[*].max_waiting : v == local.max_waiting] + ) +} + +locals { + search_path = huaweicloud_rds_pg_sql_limit.test.search_path +} +data "huaweicloud_rds_pg_sql_limits" "search_path_filter" { + depends_on = [huaweicloud_rds_pg_sql_limit.test] + + instance_id = huaweicloud_rds_instance.test.id + db_name = "%[2]s" + search_path = huaweicloud_rds_pg_sql_limit.test.search_path +} +output "search_path_filter_is_useful" { + value = length(data.huaweicloud_rds_pg_sql_limits.search_path_filter.sql_limits) > 0 && alltrue( + [for v in data.huaweicloud_rds_pg_sql_limits.search_path_filter.sql_limits[*].search_path : v == local.search_path] + ) +} + +locals { + is_effective = huaweicloud_rds_pg_sql_limit.test.is_effective +} +data "huaweicloud_rds_pg_sql_limits" "is_effective_filter" { + depends_on = [huaweicloud_rds_pg_sql_limit.test] + + instance_id = huaweicloud_rds_instance.test.id + db_name = "%[2]s" + is_effective = huaweicloud_rds_pg_sql_limit.test.is_effective +} +output "is_effective_filter_is_useful" { + value = length(data.huaweicloud_rds_pg_sql_limits.is_effective_filter.sql_limits) > 0 && alltrue( + [for v in data.huaweicloud_rds_pg_sql_limits.is_effective_filter.sql_limits[*].is_effective : v == local.is_effective] + ) +} + +locals { + query_string = huaweicloud_rds_pg_sql_limit.query_string.query_string +} +data "huaweicloud_rds_pg_sql_limits" "query_string_filter" { + depends_on = [huaweicloud_rds_pg_sql_limit.query_string] + + instance_id = huaweicloud_rds_instance.test.id + db_name = "%[2]s" + query_string = huaweicloud_rds_pg_sql_limit.query_string.query_string +} +output "query_string_filter_is_useful" { + value = length(data.huaweicloud_rds_pg_sql_limits.query_string_filter.sql_limits) > 0 && alltrue( + [for v in data.huaweicloud_rds_pg_sql_limits.query_string_filter.sql_limits[*].query_string : v == local.query_string] + ) +} +`, testPgSqlLimit_base(name), name) +} diff --git a/huaweicloud/services/rds/data_source_huaweicloud_rds_pg_sql_limits.go b/huaweicloud/services/rds/data_source_huaweicloud_rds_pg_sql_limits.go new file mode 100644 index 0000000000..ac3598d6b8 --- /dev/null +++ b/huaweicloud/services/rds/data_source_huaweicloud_rds_pg_sql_limits.go @@ -0,0 +1,210 @@ +// Generated by PMS #152 +package rds + +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/filters" + "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 DataSourceRdsPgSqlLimits() *schema.Resource { + return &schema.Resource{ + ReadContext: dataSourceRdsPgSqlLimitsRead, + + 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.`, + }, + "instance_id": { + Type: schema.TypeString, + Required: true, + Description: `Specifies the ID of RDS PostgreSQL instance.`, + }, + "db_name": { + Type: schema.TypeString, + Required: true, + Description: `Specifies the name of the database.`, + }, + "sql_limit_id": { + Type: schema.TypeString, + Optional: true, + Description: `Specifies the ID of SQL limit.`, + }, + "query_id": { + Type: schema.TypeString, + Optional: true, + Description: `Specifies the query ID.`, + }, + "query_string": { + Type: schema.TypeString, + Optional: true, + Description: `Specifies the text form of SQL statement.`, + }, + "max_concurrency": { + Type: schema.TypeString, + Optional: true, + Description: `Specifies the number of SQL statements executed simultaneously.`, + }, + "max_waiting": { + Type: schema.TypeString, + Optional: true, + Description: `Specifies the max waiting time in seconds.`, + }, + "search_path": { + Type: schema.TypeString, + Optional: true, + Description: `Specifies the query order for names that are not schema qualified.`, + }, + "is_effective": { + Type: schema.TypeString, + Optional: true, + Description: `Specifies whether the SQL limit is effective.`, + }, + "sql_limits": { + Type: schema.TypeList, + Computed: true, + Description: `Indicates the list of SQL limits.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "id": { + Type: schema.TypeString, + Computed: true, + Description: `Indicates the ID of SQL limit.`, + }, + "query_id": { + Type: schema.TypeString, + Computed: true, + Description: `Indicates the query ID.`, + }, + "query_string": { + Type: schema.TypeString, + Computed: true, + Description: `Indicates the text form of SQL statement.`, + }, + "max_concurrency": { + Type: schema.TypeInt, + Computed: true, + Description: `Indicates the number of SQL statements executed simultaneously.`, + }, + "max_waiting": { + Type: schema.TypeInt, + Computed: true, + Description: `Indicates the max waiting time in seconds.`, + }, + "search_path": { + Type: schema.TypeString, + Computed: true, + Description: `Indicates the query order for names that are not schema qualified.`, + }, + "is_effective": { + Type: schema.TypeBool, + Computed: true, + Description: `Indicates whether the SQL limit is effective.`, + }, + }, + }, + }, + }, + } +} + +type PgSqlLimitsDSWrapper struct { + *schemas.ResourceDataWrapper + Config *config.Config +} + +func newPgSqlLimitsDSWrapper(d *schema.ResourceData, meta interface{}) *PgSqlLimitsDSWrapper { + return &PgSqlLimitsDSWrapper{ + ResourceDataWrapper: schemas.NewSchemaWrapper(d), + Config: meta.(*config.Config), + } +} + +func dataSourceRdsPgSqlLimitsRead(_ context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + wrapper := newPgSqlLimitsDSWrapper(d, meta) + listSqlLimitRst, err := wrapper.ListSqlLimit() + if err != nil { + return diag.FromErr(err) + } + + id, err := uuid.GenerateUUID() + if err != nil { + return diag.FromErr(err) + } + d.SetId(id) + + err = wrapper.listSqlLimitToSchema(listSqlLimitRst) + if err != nil { + return diag.FromErr(err) + } + + return nil +} + +// @API RDS GET /v3/{project_id}/instances/{instance_id}/sql-limit +func (w *PgSqlLimitsDSWrapper) ListSqlLimit() (*gjson.Result, error) { + client, err := w.NewClient(w.Config, "rds") + if err != nil { + return nil, err + } + + d := w.ResourceData + uri := "/v3/{project_id}/instances/{instance_id}/sql-limit" + uri = strings.ReplaceAll(uri, "{instance_id}", d.Get("instance_id").(string)) + params := map[string]any{ + "db_name": w.Get("db_name"), + } + params = utils.RemoveNil(params) + return httphelper.New(client). + Method("GET"). + URI(uri). + Query(params). + OffsetPager("sql_limit_objects", "offset", "limit", 0). + Filter( + filters.New().From("sql_limit_objects"). + Where("id", "=", w.Get("sql_limit_id")). + Where("query_id", "=", w.Get("query_id")). + Where("query_string", "=", w.Get("query_string")). + Where("max_concurrency", "=", w.GetToInt("max_concurrency")). + Where("max_waiting", "=", w.GetToInt("max_waiting")). + Where("search_path", "=", w.Get("search_path")). + Where("is_effective", "=", w.GetToBool("is_effective")), + ). + Request(). + Result() +} + +func (w *PgSqlLimitsDSWrapper) listSqlLimitToSchema(body *gjson.Result) error { + d := w.ResourceData + mErr := multierror.Append(nil, + d.Set("region", w.Config.GetRegion(w.ResourceData)), + d.Set("sql_limits", schemas.SliceToList(body.Get("sql_limit_objects"), + func(sqlLimit gjson.Result) any { + return map[string]any{ + "id": sqlLimit.Get("id").Value(), + "query_id": sqlLimit.Get("query_id").Value(), + "query_string": sqlLimit.Get("query_string").Value(), + "max_concurrency": sqlLimit.Get("max_concurrency").Value(), + "max_waiting": sqlLimit.Get("max_waiting").Value(), + "search_path": sqlLimit.Get("search_path").Value(), + "is_effective": sqlLimit.Get("is_effective").Value(), + } + }, + )), + ) + return mErr.ErrorOrNil() +}