From 89515efc4bcdd1f6f0ecd19a38d64b8457c5d672 Mon Sep 17 00:00:00 2001 From: wangzepeng <852420284@qq.com> Date: Mon, 25 Dec 2023 13:14:05 +0800 Subject: [PATCH] feat(DDS): import DDS resource, unit test and document (#1039) --- docs/data-sources/dds_instances.md | 116 +++++++ docs/resources/dds_audit_log_policy.md | 62 ++++ docs/resources/dds_backup.md | 85 +++++ docs/resources/dds_parameter_template.md | 93 ++++++ ...ource_flexibleengine_dds_instances_test.go | 95 ++++++ ...lexibleengine_dds_audit_log_policy_test.go | 226 +++++++++++++ ...resource_flexibleengine_dds_backup_test.go | 194 +++++++++++ ...xibleengine_dds_parameter_template_test.go | 309 ++++++++++++++++++ ...resource_flexibleengine_rds_backup_test.go | 9 +- flexibleengine/provider.go | 9 +- 10 files changed, 1191 insertions(+), 7 deletions(-) create mode 100644 docs/data-sources/dds_instances.md create mode 100644 docs/resources/dds_audit_log_policy.md create mode 100644 docs/resources/dds_backup.md create mode 100644 docs/resources/dds_parameter_template.md create mode 100644 flexibleengine/acceptance/data_source_flexibleengine_dds_instances_test.go create mode 100644 flexibleengine/acceptance/resource_flexibleengine_dds_audit_log_policy_test.go create mode 100644 flexibleengine/acceptance/resource_flexibleengine_dds_backup_test.go create mode 100644 flexibleengine/acceptance/resource_flexibleengine_dds_parameter_template_test.go diff --git a/docs/data-sources/dds_instances.md b/docs/data-sources/dds_instances.md new file mode 100644 index 000000000..d7d6dd582 --- /dev/null +++ b/docs/data-sources/dds_instances.md @@ -0,0 +1,116 @@ +--- +subcategory: "Document Database Service (DDS)" +--- + +# flexibleengine_dds_instances + +Use this data source to get the list of DDS instances. + +## Example Usage + +```hcl +variable "vpc_id" {} +variable "subnet_id" {} + +data "flexibleengine_dds_instances" "test" { + name = "test_name" + mode = "Sharding" + vpc_id = var.vpc_id + subnet_id = var.subnet_id +} +``` + +## Argument Reference + +The following arguments are supported: + +* `region` - (Optional, String) Specifies the region in which to query the data source. If omitted, the provider-level + region will be used. + +* `name` - (Optional, String) Specifies the DB instance name. + +* `mode` - (Optional, String) Specifies the mode of the database instance. + +* `vpc_id` - (Optional, String) Specifies the VPC ID. + +* `subnet_id` - (Optional, String) Specifies the subnet Network ID. + +## Attribute Reference + +In addition to all arguments above, the following attributes are exported: + +* `id` - The resource ID. + +* `instances` - Indicates the list of DDS instances. + The [instances](#dds_instances) object structure is documented below. + + +The `instances` block supports: + +* `id` - Indicates the ID of the instance. + +* `name` - Indicates the DB instance name. + +* `ssl` - Indicates whether to enable or disable SSL. + +* `port` - Indicates the database port number. The port range is 2100 to 9500. + +* `datastore` - Indicates database information. + The [datastore](#dds_datastore) object structure is documented below. + +* `backup_strategy` - Indicates backup strategy. + The [backup_strategy](#dds_backup_strategy) object structure is documented below. + +* `vpc_id` - Indicates the VPC ID. + +* `subnet_id` - Indicates the subnet Network ID. + +* `security_group_id` - Indicates the security group ID of the DDS instance. + +* `disk_encryption_id` - Indicates the disk encryption ID of the instance. + +* `mode` - Specifies the mode of the database instance. + +* `db_username` - Indicates the DB Administrator name. + +* `status` - Indicates the DB instance status. + +* `enterprise_project_id` - Indicates the enterprise project id of the dds instance. + +* `nodes` - Indicates the instance nodes information. + The [nodes](#dds_nodes) object structure is documented below. + +* `tags` - Indicates the key/value pairs to associate with the DDS instance. + + +The `datastore` block supports: + +* `type` - Indicates the DB engine. + +* `version` - Indicates the DB instance version. + +* `storage_engine` - Indicates the storage engine of the DB instance. + + +The `backup_strategy` block supports: + +* `start_time` - Indicates the backup time window. + +* `keep_days` - Indicates the number of days to retain the generated backup files. + + +The `nodes` block supports: + +* `id` - Indicates the node ID. + +* `name` - Indicates the node name. + +* `role` - Indicates the node role. + +* `type` - Indicates the node type. + +* `private_ip` - Indicates the private IP address of a node. + +* `public_ip` - Indicates the EIP that has been bound on a node. + +* `status` - Indicates the node status. diff --git a/docs/resources/dds_audit_log_policy.md b/docs/resources/dds_audit_log_policy.md new file mode 100644 index 000000000..8d35df877 --- /dev/null +++ b/docs/resources/dds_audit_log_policy.md @@ -0,0 +1,62 @@ +--- +subcategory: "Document Database Service (DDS)" +--- + +# flexibleengine_dds_audit_log_policy + +Manages a DDS audit log policy resource within FlexibleEngine. + +## Example Usage + +```hcl +variable "instance_id" {} +variable "keep_days" {} + +resource "flexibleengine_dds_audit_log_policy" "test"{ + instance_id = var.instance_id + keep_days = var.keep_days +} +``` + +## Argument Reference + +The following arguments are supported: + +* `region` - (Optional, String, ForceNew) Specifies the region in which to create the resource. + If omitted, the provider-level region will be used. Changing this parameter will create a new resource. + +* `instance_id` - (Required, String, ForceNew) Specifies the ID of the DDS instance. + + Changing this parameter will create a new resource. + +* `keep_days` - (Required, Int) Specifies the number of days for storing audit logs. The value ranges from 7 to 732. + +* `audit_scope` - (Optional, String) Specifies the audit scope. + If this parameter is left blank or set to **all**, all audit log policies are enabled. + You can enter the database or collection name. Use commas (,) to separate multiple databases + or collections. If the name contains a comma (,), add a dollar sign ($) before the comma + to distinguish it from the separators. Enter a maximum of 1024 characters. The value + cannot contain spaces or the following special characters "[]{}():? The dollar sign ($) + can be used only in escape mode. + +* `audit_types` - (Optional, List) Specifies the audit type. The value is **auth**, **insert**, **delete**, **update**, + **query** or **command**. + +* `reserve_auditlogs` - (Optional, String) Specifies whether the historical audit logs are + retained when SQL audit is disabled. + + **true**: indicates that historical audit logs are retained when SQL audit is disabled.(default value) + + **false**: indicates that existing historical audit logs are deleted when SQL audit is disabled. + +## Attribute Reference + +In addition to all arguments above, the following attributes are exported: + +* `id` - The resource ID. + +## Import + +The DDS audit log policy can be imported using the instance ID, e.g.: + +```shell +terraform import flexibleengine_dds_audit_log_policy.test +``` diff --git a/docs/resources/dds_backup.md b/docs/resources/dds_backup.md new file mode 100644 index 000000000..ca08f4ad0 --- /dev/null +++ b/docs/resources/dds_backup.md @@ -0,0 +1,85 @@ +--- +subcategory: "Document Database Service (DDS)" +--- + +# flexibleengine_dds_backup + +Manages a DDS backup resource within FlexibleEngine. + +## Example Usage + +```hcl +variable "dds_instance_id" {} +variable "name" {} + +resource "flexibleengine_dds_backup" "test"{ + instance_id = var.dds_instance_id + name = var.name +} +``` + +## Argument Reference + +The following arguments are supported: + +* `region` - (Optional, String, ForceNew) Specifies the region in which to create the resource. + If omitted, the provider-level region will be used. Changing this parameter will create a new resource. + +* `instance_id` - (Required, String, ForceNew) Specifies the ID of a DDS instance. + Changing this parameter will create a new resource. + +* `name` - (Required, String, ForceNew) Specifies the manual backup name. + The value must be 4 to 64 characters in length and start with a letter (from A to Z or from a to z). + It is case-sensitive and can contain only letters, digits (from 0 to 9), hyphens (-), and underscores (_). + Changing this parameter will create a new resource. + +* `description` - (Optional, String, ForceNew) Specifies the manual backup description. + Changing this parameter will create a new resource. + +## Attribute Reference + +In addition to all arguments above, the following attributes are exported: + +* `id` - The resource ID. + +* `instance_name` - Indicates the name of a DDS instance. + +* `datastore` - Indicates the database version. + The [datastore](#dds_datastore) object structure is documented below. + +* `type` - Indicates the backup type. Valid value: + + **Manual**: indicates manual full backup. + +* `begin_time` - Indicates the start time of the backup. The format is yyyy-mm-dd hh:mm:ss. The value is in UTC format. + +* `end_time` - Indicates the end time of the backup. The format is yyyy-mm-dd hh:mm:ss. The value is in UTC format. + +* `status` - Indicates the backup status. Valid value: + + **BUILDING**: Backup in progress. + + **COMPLETED**: Backup completed. + + **FAILED**: Backup failed. + + **DISABLED**: Backup being deleted. + +* `size` - Indicates the backup size in KB. + + +The `datastore` block supports: + +* `type` - Indicates the DB engine. + +* `version` - Indicates the database version. The value can be **4.2**, **4.0**, or **3.4**. + +## Timeouts + +This resource provides the following timeouts configuration options: + +* `create` - Default is 30 minutes. +* `delete` - Default is 10 minutes. + +## Import + +The DDS backup can be imported using the instance ID and the backup ID separated by a slash, e.g.: + +```shell +terraform import flexibleengine_dds_backup.test 6fb8b99944c7459da32f751f0edea756br02/0ce123456a00f2591fabc00385ff1234 +``` diff --git a/docs/resources/dds_parameter_template.md b/docs/resources/dds_parameter_template.md new file mode 100644 index 000000000..7ffd5eeb9 --- /dev/null +++ b/docs/resources/dds_parameter_template.md @@ -0,0 +1,93 @@ +--- +subcategory: "Document Database Service (DDS)" +--- + +# flexibleengine_dds_parameter_template + +Manages a DDS parameter template resource within FlexibleEngine. + +## Example Usage + +```hcl +variable "name" {} +variable "parameter_values" {} +variable "node_type" {} +variable "node_version" {} + +resource "flexibleengine_dds_parameter_template" "test"{ + name = var.name + parameter_values = var.parameter_values + node_type = var.node_type + node_version = var.node_version +} +``` + +## Argument Reference + +The following arguments are supported: + +* `region` - (Optional, String, ForceNew) Specifies the region in which to create the resource. + If omitted, the provider-level region will be used. Changing this parameter will create a new resource. + +* `name` - (Required, String) Specifies the parameter template name. + The value must be 1 to 64 characters in length and start with a letter (from A to Z or from a to z). + It is case-sensitive and can contain only letters, digits (from 0 to 9), hyphens (-), and underscores (_). + +* `node_type` - (Required, String, ForceNew) Specifies the node type of parameter template node_type. Valid value: + + **mongos**: the mongos node type. + + **shard**: the shard node type. + + **config**: the config node type. + + **replica**: the replica node type. + + **single**: the single node type. + + Changing this parameter will create a new resource. + +* `node_version` - (Required, String, ForceNew) Specifies the database version. + The value can be **4.2**, **4.0** or **3.4**. + + Changing this parameter will create a new resource. + +* `parameter_values` - (Optional, Map) Specifies the mapping between parameter names and parameter values. + You can customize parameter values based on the parameters in the default parameter template. + +* `description` - (Optional, String) Specifies the parameter template description. + The description must consist of a maximum of 256 characters and cannot contain the carriage + return character or the following special characters: >!<"&'=. + +## Attribute Reference + +In addition to all arguments above, the following attributes are exported: + +* `id` - The resource ID. + +* `parameters` - Indicates the parameters defined by users based on the default parameter templates. + The [parameters](#DdsParameterTemplate_Parameter) structure is documented below. + + +The `parameters` block supports: + +* `name` - Indicates the parameter name. + +* `value` - Indicates the parameter value. + +* `description` - Indicates the parameter description. + +* `type` - Indicates the parameter type. The value can be integer, string, boolean, float, or list. + +* `value_range` - Indicates the value range. + +* `restart_required` - Indicates whether the instance needs to be restarted. + + If the value is **true**, restart is required. + + If the value is **false**, restart is not required. + +* `readonly` - Indicates whether the parameter is read-only. + + If the value is **true**, the parameter is read-only. + + If the value is **false**, the parameter is not read-only. + +## Import + +The DDS parameter template can be imported using the `id`, e.g. + +```shell +terraform import flexibleengine_dds_parameter_template.test +``` diff --git a/flexibleengine/acceptance/data_source_flexibleengine_dds_instances_test.go b/flexibleengine/acceptance/data_source_flexibleengine_dds_instances_test.go new file mode 100644 index 000000000..10679f15f --- /dev/null +++ b/flexibleengine/acceptance/data_source_flexibleengine_dds_instances_test.go @@ -0,0 +1,95 @@ +package acceptance + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/huaweicloud/terraform-provider-huaweicloud/huaweicloud/services/acceptance" +) + +func TestAccDatasourceDdsInstance_basic(t *testing.T) { + rName := "data.flexibleengine_dds_instances.test" + name := acceptance.RandomAccResourceName() + dc := acceptance.InitDataSourceCheck(rName) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + ProviderFactories: TestAccProviderFactories, + Steps: []resource.TestStep{ + { + Config: testAccDatasourceDdsInstance_basic(name), + Check: resource.ComposeTestCheckFunc( + dc.CheckResourceExists(), + resource.TestCheckResourceAttr(rName, "instances.0.name", name), + resource.TestCheckResourceAttr(rName, "instances.0.mode", "Sharding"), + ), + }, + }, + }) +} + +func testAccDatasourceDdsInstance_base(rName string) string { + return fmt.Sprintf(` +%s + +data "flexibleengine_availability_zones" "test" {} + +resource "flexibleengine_dds_instance_v3" "test" { + name = "%s" + availability_zone = data.flexibleengine_availability_zones.test.names[0] + vpc_id = flexibleengine_vpc_v1.test.id + subnet_id = flexibleengine_vpc_subnet_v1.test.id + security_group_id = flexibleengine_networking_secgroup_v2.test.id + password = "Terraform@123" + mode = "Sharding" + + datastore { + type = "DDS-Community" + version = "3.4" + storage_engine = "wiredTiger" + } + + flavor { + type = "mongos" + num = 2 + spec_code = "dds.mongodb.s3.medium.4.mongos" + } + + flavor { + type = "shard" + num = 2 + storage = "ULTRAHIGH" + size = 20 + spec_code = "dds.mongodb.s3.medium.4.shard" + } + + flavor { + type = "config" + num = 1 + storage = "ULTRAHIGH" + size = 20 + spec_code = "dds.mongodb.s3.large.2.config" + } + + backup_strategy { + start_time = "08:00-09:00" + keep_days = "8" + } + + tags = { + foo = "bar" + owner = "terraform" + } +}`, testBaseNetwork(rName), rName) +} + +func testAccDatasourceDdsInstance_basic(name string) string { + return fmt.Sprintf(` +%s + +data "flexibleengine_dds_instances" "test" { + name = flexibleengine_dds_instance_v3.test.name +} +`, testAccDatasourceDdsInstance_base(name)) +} diff --git a/flexibleengine/acceptance/resource_flexibleengine_dds_audit_log_policy_test.go b/flexibleengine/acceptance/resource_flexibleengine_dds_audit_log_policy_test.go new file mode 100644 index 000000000..ba4118f50 --- /dev/null +++ b/flexibleengine/acceptance/resource_flexibleengine_dds_audit_log_policy_test.go @@ -0,0 +1,226 @@ +package acceptance + +import ( + "fmt" + "strings" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" + + "github.com/chnsz/golangsdk" + + "github.com/huaweicloud/terraform-provider-huaweicloud/huaweicloud/config" + "github.com/huaweicloud/terraform-provider-huaweicloud/huaweicloud/services/acceptance" + "github.com/huaweicloud/terraform-provider-huaweicloud/huaweicloud/utils" +) + +func getDdsAuditLogPolicyResourceFunc(cfg *config.Config, state *terraform.ResourceState) (interface{}, error) { + region := OS_REGION_NAME + // getAuditLog: Query DDS audit log + var ( + getAuditLogPolicyHttpUrl = "v3/{project_id}/instances/{instance_id}/auditlog-policy" + getAuditLogPolicyProduct = "dds" + ) + getAuditLogPolicyClient, err := cfg.NewServiceClient(getAuditLogPolicyProduct, region) + if err != nil { + return nil, fmt.Errorf("error creating DDS Client: %s", err) + } + + instanceID := state.Primary.ID + getAuditLogPolicyPath := getAuditLogPolicyClient.Endpoint + getAuditLogPolicyHttpUrl + getAuditLogPolicyPath = strings.ReplaceAll(getAuditLogPolicyPath, "{project_id}", + getAuditLogPolicyClient.ProjectID) + getAuditLogPolicyPath = strings.ReplaceAll(getAuditLogPolicyPath, "{instance_id}", instanceID) + + getAuditLogPolicyOpt := golangsdk.RequestOpts{ + KeepResponseBody: true, + OkCodes: []int{ + 200, + }, + MoreHeaders: map[string]string{ + "Content-Type": "application/json", + }, + } + getAuditLogPolicyResp, err := getAuditLogPolicyClient.Request("GET", getAuditLogPolicyPath, &getAuditLogPolicyOpt) + if err != nil { + return nil, fmt.Errorf("error retrieving DDS audit log policy: %s", err) + } + + getAuditLogPolicyRespBody, err := utils.FlattenResponse(getAuditLogPolicyResp) + if err != nil { + return nil, err + } + + keepDays := utils.PathSearch("keep_days", getAuditLogPolicyRespBody, 0) + if keepDays.(float64) == 0 { + return nil, fmt.Errorf("the instance %s has no audit log policy", instanceID) + } + + return getAuditLogPolicyRespBody, nil +} + +func TestAccDdsAuditLogPolicy_basic(t *testing.T) { + var obj interface{} + + name := acceptance.RandomAccResourceName() + rName := "flexibleengine_dds_audit_log_policy.test" + + rc := acceptance.InitResourceCheck( + rName, + &obj, + getDdsAuditLogPolicyResourceFunc, + ) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + ProviderFactories: TestAccProviderFactories, + CheckDestroy: rc.CheckResourceDestroy(), + Steps: []resource.TestStep{ + { + Config: testDdsAuditLogPolicy_basic(name), + Check: resource.ComposeTestCheckFunc( + rc.CheckResourceExists(), + resource.TestCheckResourceAttr(rName, "keep_days", "7"), + ), + }, + { + Config: testDdsAuditLogPolicy_basic_update(name), + Check: resource.ComposeTestCheckFunc( + rc.CheckResourceExists(), + resource.TestCheckResourceAttr(rName, "keep_days", "15"), + ), + }, + { + ResourceName: rName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"instance_id"}, + }, + }, + }) +} + +func TestAccDdsAuditLogPolicy_audit_types(t *testing.T) { + var obj interface{} + + name := acceptance.RandomAccResourceName() + rName := "flexibleengine_dds_audit_log_policy.test" + + rc := acceptance.InitResourceCheck( + rName, + &obj, + getDdsAuditLogPolicyResourceFunc, + ) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + ProviderFactories: TestAccProviderFactories, + CheckDestroy: rc.CheckResourceDestroy(), + Steps: []resource.TestStep{ + { + Config: testAccDdsAuditLogPolicy_audit_types(name), + Check: resource.ComposeTestCheckFunc( + rc.CheckResourceExists(), + resource.TestCheckResourceAttr(rName, "keep_days", "7"), + resource.TestCheckResourceAttr(rName, "audit_types.#", "6"), + resource.TestCheckResourceAttrSet(rName, "audit_types.#"), + ), + }, + }, + }) +} + +func testAccResourceDdsAuditLogPolicy_base(rName string) string { + return fmt.Sprintf(` +%s + +data "flexibleengine_availability_zones" "test" {} + +resource "flexibleengine_dds_instance_v3" "test" { + name = "%s" + availability_zone = data.flexibleengine_availability_zones.test.names[0] + vpc_id = flexibleengine_vpc_v1.test.id + subnet_id = flexibleengine_vpc_subnet_v1.test.id + security_group_id = flexibleengine_networking_secgroup_v2.test.id + password = "Terraform@123" + mode = "Sharding" + + datastore { + type = "DDS-Community" + version = "3.4" + storage_engine = "wiredTiger" + } + + flavor { + type = "mongos" + num = 2 + spec_code = "dds.mongodb.s3.medium.4.mongos" + } + + flavor { + type = "shard" + num = 2 + storage = "ULTRAHIGH" + size = 20 + spec_code = "dds.mongodb.s3.medium.4.shard" + } + + flavor { + type = "config" + num = 1 + storage = "ULTRAHIGH" + size = 20 + spec_code = "dds.mongodb.s3.large.2.config" + } + + backup_strategy { + start_time = "08:00-09:00" + keep_days = "8" + } + + tags = { + foo = "bar" + owner = "terraform" + } +}`, testBaseNetwork(rName), rName) +} + +func testDdsAuditLogPolicy_basic(name string) string { + return fmt.Sprintf(` +%s + +resource "flexibleengine_dds_audit_log_policy" "test" { + instance_id = flexibleengine_dds_instance_v3.test.id + keep_days = 7 + reserve_auditlogs = true +} +`, testAccResourceDdsAuditLogPolicy_base(name)) +} + +func testDdsAuditLogPolicy_basic_update(name string) string { + return fmt.Sprintf(` +%s + +resource "flexibleengine_dds_audit_log_policy" "test" { + instance_id = flexibleengine_dds_instance_v3.test.id + keep_days = 15 + reserve_auditlogs = false +} +`, testAccResourceDdsAuditLogPolicy_base(name)) +} + +func testAccDdsAuditLogPolicy_audit_types(name string) string { + return fmt.Sprintf(` +%s + +resource "flexibleengine_dds_audit_log_policy" "test" { + instance_id = flexibleengine_dds_instance_v3.test.id + keep_days = 7 + + audit_types = [ + "delete", "insert", "update", "query", "auth", "command" + ] +} +`, testAccResourceDdsAuditLogPolicy_base(name)) +} diff --git a/flexibleengine/acceptance/resource_flexibleengine_dds_backup_test.go b/flexibleengine/acceptance/resource_flexibleengine_dds_backup_test.go new file mode 100644 index 000000000..9ad35c0de --- /dev/null +++ b/flexibleengine/acceptance/resource_flexibleengine_dds_backup_test.go @@ -0,0 +1,194 @@ +package acceptance + +import ( + "fmt" + "strings" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" + + "github.com/chnsz/golangsdk" + + "github.com/huaweicloud/terraform-provider-huaweicloud/huaweicloud/config" + "github.com/huaweicloud/terraform-provider-huaweicloud/huaweicloud/services/acceptance" + "github.com/huaweicloud/terraform-provider-huaweicloud/huaweicloud/utils" +) + +func getDdsBackupResourceFunc(cfg *config.Config, state *terraform.ResourceState) (interface{}, error) { + region := OS_REGION_NAME + // getBackup: Query DDS backup + var ( + getBackupHttpUrl = "v3/{project_id}/backups" + getBackupProduct = "dds" + ) + getBackupClient, err := cfg.NewServiceClient(getBackupProduct, region) + if err != nil { + return nil, fmt.Errorf("error creating DDS Client: %s", err) + } + + getBackupPath := getBackupClient.Endpoint + getBackupHttpUrl + getBackupPath = strings.ReplaceAll(getBackupPath, "{project_id}", getBackupClient.ProjectID) + + instanceId := state.Primary.Attributes["instance_id"] + backupId := state.Primary.ID + getBackupQueryParams := buildGetBackupQueryParams(instanceId, backupId) + getBackupPath += getBackupQueryParams + + getBackupOpt := golangsdk.RequestOpts{ + KeepResponseBody: true, + OkCodes: []int{ + 200, + }, + } + getBackupResp, err := getBackupClient.Request("GET", getBackupPath, &getBackupOpt) + if err != nil { + return nil, fmt.Errorf("error retrieving DdsBackup: %s", err) + } + getBackupRespBody, err := utils.FlattenResponse(getBackupResp) + if err != nil { + return nil, err + } + backups := utils.PathSearch("backups", getBackupRespBody, make([]interface{}, 0)).([]interface{}) + if len(backups) == 0 { + return nil, fmt.Errorf("error get backup by backup ID %s", backupId) + } + + return backups[0], nil +} + +func buildGetBackupQueryParams(instanceId, backupId string) string { + res := "" + if instanceId != "" { + res = fmt.Sprintf("%s&instance_id=%v", res, instanceId) + } + if backupId != "" { + res = fmt.Sprintf("%s&backup_id=%v", res, backupId) + } + if res != "" { + res = "?" + res[1:] + } + return res +} + +func TestAccDdsBackup_basic(t *testing.T) { + var obj interface{} + + name := acceptance.RandomAccResourceName() + rName := "flexibleengine_dds_backup.test" + + rc := acceptance.InitResourceCheck( + rName, + &obj, + getDdsBackupResourceFunc, + ) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + ProviderFactories: TestAccProviderFactories, + CheckDestroy: rc.CheckResourceDestroy(), + Steps: []resource.TestStep{ + { + Config: testDdsBackup_basic(name), + Check: resource.ComposeTestCheckFunc( + rc.CheckResourceExists(), + resource.TestCheckResourceAttr(rName, "name", name), + resource.TestCheckResourceAttr(rName, "description", "this is a test dds instance"), + resource.TestCheckResourceAttr(rName, "type", "Manual"), + resource.TestCheckResourceAttr(rName, "status", "COMPLETED"), + resource.TestCheckResourceAttr(rName, "datastore.0.type", "DDS-Community"), + acceptance.TestCheckResourceAttrWithVariable(rName, "instance_name", + "${flexibleengine_dds_instance_v3.instance.name}"), + acceptance.TestCheckResourceAttrWithVariable(rName, "datastore.0.version", + "${flexibleengine_dds_instance_v3.instance.datastore.0.version}"), + ), + }, + { + ResourceName: rName, + ImportState: true, + ImportStateVerify: true, + ImportStateIdFunc: testAccDdsBackupImportStateFunc(rName), + }, + }, + }) +} + +func testAccResourceDdsBackup_base(rName string) string { + return fmt.Sprintf(` +%s + +data "flexibleengine_availability_zones" "test" {} + +resource "flexibleengine_dds_instance_v3" "instance" { + name = "%s" + availability_zone = data.flexibleengine_availability_zones.test.names[0] + vpc_id = flexibleengine_vpc_v1.test.id + subnet_id = flexibleengine_vpc_subnet_v1.test.id + security_group_id = flexibleengine_networking_secgroup_v2.test.id + password = "Terraform@123" + mode = "Sharding" + + datastore { + type = "DDS-Community" + version = "3.4" + storage_engine = "wiredTiger" + } + + flavor { + type = "mongos" + num = 2 + spec_code = "dds.mongodb.s3.medium.4.mongos" + } + + flavor { + type = "shard" + num = 2 + storage = "ULTRAHIGH" + size = 20 + spec_code = "dds.mongodb.s3.medium.4.shard" + } + + flavor { + type = "config" + num = 1 + storage = "ULTRAHIGH" + size = 20 + spec_code = "dds.mongodb.s3.large.2.config" + } + + backup_strategy { + start_time = "08:00-09:00" + keep_days = "8" + } + + tags = { + foo = "bar" + owner = "terraform" + } +}`, testBaseNetwork(rName), rName) +} + +func testDdsBackup_basic(name string) string { + return fmt.Sprintf(` +%s + +resource "flexibleengine_dds_backup" "test" { + instance_id = flexibleengine_dds_instance_v3.instance.id + name = "%s" + description = "this is a test dds instance" +} +`, testAccResourceDdsBackup_base(name), name) +} + +func testAccDdsBackupImportStateFunc(name string) resource.ImportStateIdFunc { + return func(s *terraform.State) (string, error) { + rs, ok := s.RootModule().Resources[name] + if !ok { + return "", fmt.Errorf("resource (%s) not found: %s", name, rs) + } + if rs.Primary.ID == "" || rs.Primary.Attributes["instance_id"] == "" { + return "", fmt.Errorf("resource (%s) not found: %s", name, rs) + } + return fmt.Sprintf("%s/%s", rs.Primary.Attributes["instance_id"], rs.Primary.ID), nil + } +} diff --git a/flexibleengine/acceptance/resource_flexibleengine_dds_parameter_template_test.go b/flexibleengine/acceptance/resource_flexibleengine_dds_parameter_template_test.go new file mode 100644 index 000000000..56dd153a9 --- /dev/null +++ b/flexibleengine/acceptance/resource_flexibleengine_dds_parameter_template_test.go @@ -0,0 +1,309 @@ +package acceptance + +import ( + "fmt" + "strings" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" + + "github.com/chnsz/golangsdk" + + "github.com/huaweicloud/terraform-provider-huaweicloud/huaweicloud/config" + "github.com/huaweicloud/terraform-provider-huaweicloud/huaweicloud/services/acceptance" + "github.com/huaweicloud/terraform-provider-huaweicloud/huaweicloud/utils" +) + +func getDdsParameterTemplateResourceFunc(cfg *config.Config, state *terraform.ResourceState) (interface{}, error) { + region := OS_REGION_NAME + // getParameterTemplate: Query DDS parameter template + var ( + getParameterTemplateHttpUrl = "v3/{project_id}/configurations/{config_id}" + getParameterTemplateProduct = "dds" + ) + getParameterTemplateClient, err := cfg.NewServiceClient(getParameterTemplateProduct, region) + if err != nil { + return nil, fmt.Errorf("error creating DDS Client: %s", err) + } + + getParameterTemplatePath := getParameterTemplateClient.Endpoint + getParameterTemplateHttpUrl + getParameterTemplatePath = strings.ReplaceAll(getParameterTemplatePath, "{project_id}", + getParameterTemplateClient.ProjectID) + getParameterTemplatePath = strings.ReplaceAll(getParameterTemplatePath, "{config_id}", state.Primary.ID) + + getParameterTemplateOpt := golangsdk.RequestOpts{ + KeepResponseBody: true, + OkCodes: []int{ + 200, + }, + MoreHeaders: map[string]string{ + "Content-Type": "application/json", + }, + } + getParameterTemplateResp, err := getParameterTemplateClient.Request("GET", + getParameterTemplatePath, &getParameterTemplateOpt) + if err != nil { + return nil, fmt.Errorf("error retrieving DDS parameter template: %s", err) + } + return utils.FlattenResponse(getParameterTemplateResp) +} + +func TestAccDdsParameterTemplate_basic(t *testing.T) { + var obj interface{} + + name := acceptance.RandomAccResourceName() + updateName := acceptance.RandomAccResourceName() + rName := "flexibleengine_dds_parameter_template.test" + + rc := acceptance.InitResourceCheck( + rName, + &obj, + getDdsParameterTemplateResourceFunc, + ) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + ProviderFactories: TestAccProviderFactories, + CheckDestroy: rc.CheckResourceDestroy(), + Steps: []resource.TestStep{ + { + Config: testDdsParameterTemplate_basic(name), + Check: resource.ComposeTestCheckFunc( + rc.CheckResourceExists(), + resource.TestCheckResourceAttr(rName, "name", name), + resource.TestCheckResourceAttr(rName, "description", "test description"), + resource.TestCheckResourceAttr(rName, "node_version", "4.0"), + resource.TestCheckResourceAttr(rName, "parameters.0.name", + "connPoolMaxConnsPerHost"), + resource.TestCheckResourceAttr(rName, "parameters.0.value", "800"), + resource.TestCheckResourceAttr(rName, "parameters.1.name", + "connPoolMaxShardedConnsPerHost"), + resource.TestCheckResourceAttr(rName, "parameters.1.value", "800"), + ), + }, + { + Config: testDdsParameterTemplate_basic_update(updateName), + Check: resource.ComposeTestCheckFunc( + rc.CheckResourceExists(), + resource.TestCheckResourceAttr(rName, "name", updateName), + resource.TestCheckResourceAttr(rName, "description", "test description update"), + resource.TestCheckResourceAttr(rName, "node_type", "mongos"), + resource.TestCheckResourceAttr(rName, "node_version", "4.0"), + resource.TestCheckResourceAttr(rName, "parameters.0.name", + "connPoolMaxConnsPerHost"), + resource.TestCheckResourceAttr(rName, "parameters.0.value", "500"), + resource.TestCheckResourceAttr(rName, "parameters.1.name", + "connPoolMaxShardedConnsPerHost"), + resource.TestCheckResourceAttr(rName, "parameters.1.value", "500"), + ), + }, + { + ResourceName: rName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"node_type", "parameter_values"}, + }, + }, + }) +} + +func TestAccDdsParameterTemplate_shared_basic(t *testing.T) { + var obj interface{} + + name := acceptance.RandomAccResourceName() + rName := "flexibleengine_dds_parameter_template.test" + + rc := acceptance.InitResourceCheck( + rName, + &obj, + getDdsParameterTemplateResourceFunc, + ) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + ProviderFactories: TestAccProviderFactories, + CheckDestroy: rc.CheckResourceDestroy(), + Steps: []resource.TestStep{ + { + Config: testDdsParameterTemplate_shared_basic(name), + Check: resource.ComposeTestCheckFunc( + rc.CheckResourceExists(), + resource.TestCheckResourceAttr(rName, "name", name), + resource.TestCheckResourceAttr(rName, "description", "test description shared node_type"), + resource.TestCheckResourceAttr(rName, "node_type", "shard"), + resource.TestCheckResourceAttr(rName, "node_version", "4.2"), + ), + }, + }, + }) +} + +func TestAccDdsParameterTemplate_config_basic(t *testing.T) { + var obj interface{} + + name := acceptance.RandomAccResourceName() + rName := "flexibleengine_dds_parameter_template.test" + + rc := acceptance.InitResourceCheck( + rName, + &obj, + getDdsParameterTemplateResourceFunc, + ) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + ProviderFactories: TestAccProviderFactories, + CheckDestroy: rc.CheckResourceDestroy(), + Steps: []resource.TestStep{ + { + Config: testDdsParameterTemplate_config_basic(name), + Check: resource.ComposeTestCheckFunc( + rc.CheckResourceExists(), + resource.TestCheckResourceAttr(rName, "name", name), + resource.TestCheckResourceAttr(rName, "description", "test description config node_type"), + resource.TestCheckResourceAttr(rName, "node_type", "config"), + resource.TestCheckResourceAttr(rName, "node_version", "3.4"), + ), + }, + }, + }) +} + +func TestAccDdsParameterTemplate_replica_basic(t *testing.T) { + var obj interface{} + + name := acceptance.RandomAccResourceName() + rName := "flexibleengine_dds_parameter_template.test" + + rc := acceptance.InitResourceCheck( + rName, + &obj, + getDdsParameterTemplateResourceFunc, + ) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + ProviderFactories: TestAccProviderFactories, + CheckDestroy: rc.CheckResourceDestroy(), + Steps: []resource.TestStep{ + { + Config: testDdsParameterTemplate_replica_basic(name), + Check: resource.ComposeTestCheckFunc( + rc.CheckResourceExists(), + resource.TestCheckResourceAttr(rName, "name", name), + resource.TestCheckResourceAttr(rName, "description", "test description replica node_type"), + resource.TestCheckResourceAttr(rName, "node_type", "replica"), + resource.TestCheckResourceAttr(rName, "node_version", "4.0"), + ), + }, + }, + }) +} + +func TestAccDdsParameterTemplate_single_basic(t *testing.T) { + var obj interface{} + + name := acceptance.RandomAccResourceName() + rName := "flexibleengine_dds_parameter_template.test" + + rc := acceptance.InitResourceCheck( + rName, + &obj, + getDdsParameterTemplateResourceFunc, + ) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + ProviderFactories: TestAccProviderFactories, + CheckDestroy: rc.CheckResourceDestroy(), + Steps: []resource.TestStep{ + { + Config: testDdsParameterTemplate_single_basic(name), + Check: resource.ComposeTestCheckFunc( + rc.CheckResourceExists(), + resource.TestCheckResourceAttr(rName, "name", name), + resource.TestCheckResourceAttr(rName, "description", "test description single node_type"), + resource.TestCheckResourceAttr(rName, "node_type", "single"), + resource.TestCheckResourceAttr(rName, "node_version", "4.0"), + ), + }, + }, + }) +} + +func testDdsParameterTemplate_basic(name string) string { + return fmt.Sprintf(` +resource "flexibleengine_dds_parameter_template" "test" { + name = "%s" + description = "test description" + node_type = "mongos" + node_version = "4.0" + + parameter_values = { + connPoolMaxConnsPerHost = 800 + connPoolMaxShardedConnsPerHost = 800 + } +} +`, name) +} + +func testDdsParameterTemplate_basic_update(name string) string { + return fmt.Sprintf(` +resource "flexibleengine_dds_parameter_template" "test" { + name = "%s" + description = "test description update" + node_type = "mongos" + node_version = "4.0" + + parameter_values = { + connPoolMaxConnsPerHost = 500 + connPoolMaxShardedConnsPerHost = 500 + } +} +`, name) +} + +func testDdsParameterTemplate_shared_basic(name string) string { + return fmt.Sprintf(` +resource "flexibleengine_dds_parameter_template" "test" { + name = "%s" + description = "test description shared node_type" + node_type = "shard" + node_version = "4.2" +} +`, name) +} + +func testDdsParameterTemplate_config_basic(name string) string { + return fmt.Sprintf(` +resource "flexibleengine_dds_parameter_template" "test" { + name = "%s" + description = "test description config node_type" + node_type = "config" + node_version = "3.4" +} +`, name) +} + +func testDdsParameterTemplate_replica_basic(name string) string { + return fmt.Sprintf(` +resource "flexibleengine_dds_parameter_template" "test" { + name = "%s" + description = "test description replica node_type" + node_type = "replica" + node_version = "4.0" +} +`, name) +} + +func testDdsParameterTemplate_single_basic(name string) string { + return fmt.Sprintf(` +resource "flexibleengine_dds_parameter_template" "test" { + name = "%s" + description = "test description single node_type" + node_type = "single" + node_version = "4.0" +} +`, name) +} diff --git a/flexibleengine/acceptance/resource_flexibleengine_rds_backup_test.go b/flexibleengine/acceptance/resource_flexibleengine_rds_backup_test.go index 514276fb1..2efa7ec34 100644 --- a/flexibleengine/acceptance/resource_flexibleengine_rds_backup_test.go +++ b/flexibleengine/acceptance/resource_flexibleengine_rds_backup_test.go @@ -90,7 +90,7 @@ func TestAccBackup_mysql_basic(t *testing.T) { ResourceName: rName, ImportState: true, ImportStateVerify: true, - ImportStateIdFunc: testAccBackupImportStateFunc(rName), + ImportStateIdFunc: testAccRdsBackupImportStateFunc(rName), }, }, }) @@ -129,7 +129,7 @@ func TestAccBackup_sqlserver_basic(t *testing.T) { ResourceName: rName, ImportState: true, ImportStateVerify: true, - ImportStateIdFunc: testAccBackupImportStateFunc(rName), + ImportStateIdFunc: testAccRdsBackupImportStateFunc(rName), }, }, }) @@ -168,7 +168,7 @@ func TestAccBackup_pg_basic(t *testing.T) { ResourceName: rName, ImportState: true, ImportStateVerify: true, - ImportStateIdFunc: testAccBackupImportStateFunc(rName), + ImportStateIdFunc: testAccRdsBackupImportStateFunc(rName), }, }, }) @@ -211,7 +211,6 @@ resource "flexibleengine_rds_instance_v3" "test" { type = "COMMON" size = 60 } - backup_strategy { start_time = "08:00-09:00" keep_days = 1 @@ -343,7 +342,7 @@ resource "flexibleengine_rds_backup" "test" { `, testVpc(name), name) } -func testAccBackupImportStateFunc(name string) resource.ImportStateIdFunc { +func testAccRdsBackupImportStateFunc(name string) resource.ImportStateIdFunc { return func(s *terraform.State) (string, error) { rs, ok := s.RootModule().Resources[name] if !ok { diff --git a/flexibleengine/provider.go b/flexibleengine/provider.go index b5a704075..7b3b7e0d8 100644 --- a/flexibleengine/provider.go +++ b/flexibleengine/provider.go @@ -307,6 +307,8 @@ func Provider() *schema.Provider { "flexibleengine_ddm_schemas": ddm.DataSourceDdmSchemas(), "flexibleengine_ddm_accounts": ddm.DataSourceDdmAccounts(), + "flexibleengine_dds_instances": dds.DataSourceDdsInstance(), + "flexibleengine_dms_kafka_instances": dms.DataSourceDmsKafkaInstances(), "flexibleengine_dms_kafka_flavors": dms.DataSourceKafkaFlavors(), "flexibleengine_dms_rocketmq_broker": dms.DataSourceDmsRocketMQBroker(), @@ -529,8 +531,11 @@ func Provider() *schema.Provider { "flexibleengine_ddm_schema": ddm.ResourceDdmSchema(), "flexibleengine_ddm_account": ddm.ResourceDdmAccount(), - "flexibleengine_dds_database_role": dds.ResourceDatabaseRole(), - "flexibleengine_dds_database_user": dds.ResourceDatabaseUser(), + "flexibleengine_dds_audit_log_policy": dds.ResourceDdsAuditLogPolicy(), + "flexibleengine_dds_backup": dds.ResourceDdsBackup(), + "flexibleengine_dds_database_role": dds.ResourceDatabaseRole(), + "flexibleengine_dds_database_user": dds.ResourceDatabaseUser(), + "flexibleengine_dds_parameter_template": dds.ResourceDdsParameterTemplate(), "flexibleengine_apig_vpc_channel": deprecated.ResourceApigVpcChannelV2(),