diff --git a/common/common_volcengine_version.go b/common/common_volcengine_version.go index c400f2c9..6b05a93e 100644 --- a/common/common_volcengine_version.go +++ b/common/common_volcengine_version.go @@ -2,5 +2,5 @@ package common const ( TerraformProviderName = "terraform-provider-volcengine" - TerraformProviderVersion = "0.0.154" + TerraformProviderVersion = "0.0.155" ) diff --git a/docgen/main.go b/docgen/main.go index 6bff85b6..0fa5c39d 100644 --- a/docgen/main.go +++ b/docgen/main.go @@ -162,6 +162,7 @@ var resourceKeys = map[string]string{ "kafka": "KAFKA", "private_zone": "PRIVATE_ZONE", "vepfs": "VEPFS", + "vedb_mysql": "VEDB_MYSQL", } type Products struct { diff --git a/example/dataTlsProjects/main.tf b/example/dataTlsProjects/main.tf index c3e190bd..d3a8b47f 100644 --- a/example/dataTlsProjects/main.tf +++ b/example/dataTlsProjects/main.tf @@ -1,3 +1,3 @@ data "volcengine_tls_projects" "default" { - project_id = "e020c978-4f05-40e1-9167-0113d3ef****" -} \ No newline at end of file + #project_id = "e020c978-4f05-40e1-9167-0113d3ef****" +} diff --git a/example/dataVedbMysqlAccounts/main.tf b/example/dataVedbMysqlAccounts/main.tf new file mode 100644 index 00000000..1537f488 --- /dev/null +++ b/example/dataVedbMysqlAccounts/main.tf @@ -0,0 +1,57 @@ +data "volcengine_zones" "foo"{ +} + +resource "volcengine_vpc" "foo" { + vpc_name = "acc-test-vpc" + cidr_block = "172.16.0.0/16" +} + +resource "volcengine_subnet" "foo" { + subnet_name = "acc-test-subnet" + cidr_block = "172.16.0.0/24" + zone_id = data.volcengine_zones.foo.zones[2].id + vpc_id = volcengine_vpc.foo.id +} + + +resource "volcengine_vedb_mysql_instance" "foo" { + charge_type = "PostPaid" + storage_charge_type = "PostPaid" + db_engine_version = "MySQL_8_0" + db_minor_version = "3.0" + node_number = 2 + node_spec = "vedb.mysql.x4.large" + subnet_id = volcengine_subnet.foo.id + instance_name = "tf-test" + project_name = "testA" + tags { + key = "tftest" + value = "tftest" + } + tags { + key = "tftest2" + value = "tftest2" + } +} + +resource "volcengine_vedb_mysql_database" "foo" { + db_name = "tf-table" + instance_id = volcengine_vedb_mysql_instance.foo.id +} + +resource "volcengine_vedb_mysql_account" "foo" { + account_name = "tftest" + account_password = "93f0cb0614Aab12" + account_type = "Normal" + instance_id = volcengine_vedb_mysql_instance.foo.id + account_privileges { + db_name = volcengine_vedb_mysql_database.foo.db_name + account_privilege = "Custom" + account_privilege_detail = "SELECT,INSERT,DELETE" + } +} + +data "volcengine_vedb_mysql_accounts" "foo"{ + account_name = volcengine_vedb_mysql_account.foo.account_name + instance_id = volcengine_vedb_mysql_instance.foo.id +} \ No newline at end of file diff --git a/example/dataVedbMysqlAllowlists/main.tf b/example/dataVedbMysqlAllowlists/main.tf new file mode 100644 index 00000000..abb15093 --- /dev/null +++ b/example/dataVedbMysqlAllowlists/main.tf @@ -0,0 +1,51 @@ +resource "volcengine_vedb_mysql_allowlist" "foo" { + allow_list_name = "acc-test-allowlist" + allow_list_desc = "acc-test" + allow_list_type = "IPv4" + allow_list = ["192.168.0.0/24", "192.168.1.0/24", "192.168.2.0/24"] +} + +data "volcengine_zones" "foo"{ +} + +resource "volcengine_vpc" "foo" { + vpc_name = "acc-test-vpc" + cidr_block = "172.16.0.0/16" +} + +resource "volcengine_subnet" "foo" { + subnet_name = "acc-test-subnet" + cidr_block = "172.16.0.0/24" + zone_id = data.volcengine_zones.foo.zones[2].id + vpc_id = volcengine_vpc.foo.id +} + + +resource "volcengine_vedb_mysql_instance" "foo" { + charge_type = "PostPaid" + storage_charge_type = "PostPaid" + db_engine_version = "MySQL_8_0" + db_minor_version = "3.0" + node_number = 2 + node_spec = "vedb.mysql.x4.large" + subnet_id = volcengine_subnet.foo.id + instance_name = "tf-test" + project_name = "testA" + tags { + key = "tftest" + value = "tftest" + } + tags { + key = "tftest2" + value = "tftest2" + } +} + +resource "volcengine_vedb_mysql_allowlist_associate" "foo" { + allow_list_id = volcengine_vedb_mysql_allowlist.foo.id + instance_id = volcengine_vedb_mysql_instance.foo.id +} + +data "volcengine_vedb_mysql_allowlists" "foo"{ + instance_id = volcengine_vedb_mysql_instance.foo.id +} \ No newline at end of file diff --git a/example/dataVedbMysqlBackups/main.tf b/example/dataVedbMysqlBackups/main.tf new file mode 100644 index 00000000..d56d2bc3 --- /dev/null +++ b/example/dataVedbMysqlBackups/main.tf @@ -0,0 +1,48 @@ +data "volcengine_zones" "foo"{ +} + +resource "volcengine_vpc" "foo" { + vpc_name = "acc-test-vpc" + cidr_block = "172.16.0.0/16" +} + +resource "volcengine_subnet" "foo" { + subnet_name = "acc-test-subnet" + cidr_block = "172.16.0.0/24" + zone_id = data.volcengine_zones.foo.zones[2].id + vpc_id = volcengine_vpc.foo.id +} + + +resource "volcengine_vedb_mysql_instance" "foo" { + charge_type = "PostPaid" + storage_charge_type = "PostPaid" + db_engine_version = "MySQL_8_0" + db_minor_version = "3.0" + node_number = 2 + node_spec = "vedb.mysql.x4.large" + subnet_id = volcengine_subnet.foo.id + instance_name = "tf-test" + project_name = "testA" + tags { + key = "tftest" + value = "tftest" + } + tags { + key = "tftest2" + value = "tftest2" + } +} + +resource "volcengine_vedb_mysql_backup" "foo" { + instance_id = volcengine_vedb_mysql_instance.foo.id + backup_policy { + backup_time = "18:00Z-20:00Z" + full_backup_period = "Monday,Tuesday,Wednesday" + backup_retention_period = 8 + } +} + +data "volcengine_vedb_mysql_backups" "foo"{ + instance_id = volcengine_vedb_mysql_instance.foo.id +} \ No newline at end of file diff --git a/example/dataVedbMysqlDatabases/main.tf b/example/dataVedbMysqlDatabases/main.tf new file mode 100644 index 00000000..712f80e4 --- /dev/null +++ b/example/dataVedbMysqlDatabases/main.tf @@ -0,0 +1,45 @@ +data "volcengine_zones" "foo"{ +} + +resource "volcengine_vpc" "foo" { + vpc_name = "acc-test-vpc" + cidr_block = "172.16.0.0/16" +} + +resource "volcengine_subnet" "foo" { + subnet_name = "acc-test-subnet" + cidr_block = "172.16.0.0/24" + zone_id = data.volcengine_zones.foo.zones[2].id + vpc_id = volcengine_vpc.foo.id +} + + +resource "volcengine_vedb_mysql_instance" "foo" { + charge_type = "PostPaid" + storage_charge_type = "PostPaid" + db_engine_version = "MySQL_8_0" + db_minor_version = "3.0" + node_number = 2 + node_spec = "vedb.mysql.x4.large" + subnet_id = volcengine_subnet.foo.id + instance_name = "tf-test" + project_name = "testA" + tags { + key = "tftest" + value = "tftest" + } + tags { + key = "tftest2" + value = "tftest2" + } +} + +resource "volcengine_vedb_mysql_database" "foo" { + db_name = "tf-table" + instance_id = volcengine_vedb_mysql_instance.foo.id +} + +data "volcengine_vedb_mysql_databases" "foo"{ + db_name = volcengine_vedb_mysql_database.foo.db_name + instance_id = volcengine_vedb_mysql_instance.foo.id +} \ No newline at end of file diff --git a/example/dataVedbMysqlEndpoints/main.tf b/example/dataVedbMysqlEndpoints/main.tf new file mode 100644 index 00000000..f99a2e80 --- /dev/null +++ b/example/dataVedbMysqlEndpoints/main.tf @@ -0,0 +1,57 @@ +data "volcengine_zones" "foo"{ +} + +resource "volcengine_vpc" "foo" { + vpc_name = "acc-test-vpc" + cidr_block = "172.16.0.0/16" +} + +resource "volcengine_subnet" "foo" { + subnet_name = "acc-test-subnet" + cidr_block = "172.16.0.0/24" + zone_id = data.volcengine_zones.foo.zones[2].id + vpc_id = volcengine_vpc.foo.id +} + + +resource "volcengine_vedb_mysql_instance" "foo" { + charge_type = "PostPaid" + storage_charge_type = "PostPaid" + db_engine_version = "MySQL_8_0" + db_minor_version = "3.0" + node_number = 2 + node_spec = "vedb.mysql.x4.large" + subnet_id = volcengine_subnet.foo.id + instance_name = "tf-test" + project_name = "testA" + tags { + key = "tftest" + value = "tftest" + } + tags { + key = "tftest2" + value = "tftest2" + } +} +data "volcengine_vedb_mysql_instances" "foo"{ + instance_id = volcengine_vedb_mysql_instance.foo.id +} + +resource "volcengine_vedb_mysql_endpoint" "foo" { + endpoint_type = "Custom" + instance_id = volcengine_vedb_mysql_instance.foo.id + node_ids = [data.volcengine_vedb_mysql_instances.foo.instances[0].nodes[0].node_id, data.volcengine_vedb_mysql_instances.foo.instances[0].nodes[1].node_id] + read_write_mode = "ReadWrite" + endpoint_name = "tf-test" + description = "tf test" + master_accept_read_requests = true + distributed_transaction = true + consist_level = "Session" + consist_timeout = 100000 + consist_timeout_action = "ReadMaster" +} + +data "volcengine_vedb_mysql_endpoints" "foo"{ + endpoint_id = volcengine_vedb_mysql_endpoint.foo.endpoint_id + instance_id = volcengine_vedb_mysql_instance.foo.id +} \ No newline at end of file diff --git a/example/dataVedbMysqlInstances/main.tf b/example/dataVedbMysqlInstances/main.tf new file mode 100644 index 00000000..ccf70d56 --- /dev/null +++ b/example/dataVedbMysqlInstances/main.tf @@ -0,0 +1,39 @@ +data "volcengine_zones" "foo"{ +} + +resource "volcengine_vpc" "foo" { + vpc_name = "acc-test-vpc" + cidr_block = "172.16.0.0/16" +} + +resource "volcengine_subnet" "foo" { + subnet_name = "acc-test-subnet" + cidr_block = "172.16.0.0/24" + zone_id = data.volcengine_zones.foo.zones[2].id + vpc_id = volcengine_vpc.foo.id +} + + +resource "volcengine_vedb_mysql_instance" "foo" { + charge_type = "PostPaid" + storage_charge_type = "PostPaid" + db_engine_version = "MySQL_8_0" + db_minor_version = "3.0" + node_number = 2 + node_spec = "vedb.mysql.x4.large" + subnet_id = volcengine_subnet.foo.id + instance_name = "tf-test" + project_name = "testA" + tags { + key = "tftest" + value = "tftest" + } + tags { + key = "tftest2" + value = "tftest2" + } +} + +data "volcengine_vedb_mysql_instances" "foo"{ + instance_id = volcengine_vedb_mysql_instance.foo.id +} \ No newline at end of file diff --git a/example/vedbMysqlAccount/main.tf b/example/vedbMysqlAccount/main.tf new file mode 100644 index 00000000..ed86694e --- /dev/null +++ b/example/vedbMysqlAccount/main.tf @@ -0,0 +1,52 @@ +data "volcengine_zones" "foo"{ +} + +resource "volcengine_vpc" "foo" { + vpc_name = "acc-test-vpc" + cidr_block = "172.16.0.0/16" +} + +resource "volcengine_subnet" "foo" { + subnet_name = "acc-test-subnet" + cidr_block = "172.16.0.0/24" + zone_id = data.volcengine_zones.foo.zones[2].id + vpc_id = volcengine_vpc.foo.id +} + + +resource "volcengine_vedb_mysql_instance" "foo" { + charge_type = "PostPaid" + storage_charge_type = "PostPaid" + db_engine_version = "MySQL_8_0" + db_minor_version = "3.0" + node_number = 2 + node_spec = "vedb.mysql.x4.large" + subnet_id = volcengine_subnet.foo.id + instance_name = "tf-test" + project_name = "testA" + tags { + key = "tftest" + value = "tftest" + } + tags { + key = "tftest2" + value = "tftest2" + } +} + +resource "volcengine_vedb_mysql_database" "foo" { + db_name = "tf-table" + instance_id = volcengine_vedb_mysql_instance.foo.id +} + +resource "volcengine_vedb_mysql_account" "foo" { + account_name = "tftest" + account_password = "93f0cb0614Aab12" + account_type = "Normal" + instance_id = volcengine_vedb_mysql_instance.foo.id + account_privileges { + db_name = volcengine_vedb_mysql_database.foo.db_name + account_privilege = "Custom" + account_privilege_detail = "SELECT,INSERT,DELETE" + } +} \ No newline at end of file diff --git a/example/vedbMysqlAllowlist/main.tf b/example/vedbMysqlAllowlist/main.tf new file mode 100644 index 00000000..2817aa9c --- /dev/null +++ b/example/vedbMysqlAllowlist/main.tf @@ -0,0 +1,6 @@ +resource "volcengine_vedb_mysql_allowlist" "foo" { + allow_list_name = "acc-test-allowlist" + allow_list_desc = "acc-test" + allow_list_type = "IPv4" + allow_list = ["192.168.0.0/24", "192.168.1.0/24", "192.168.2.0/24"] +} \ No newline at end of file diff --git a/example/vedbMysqlAllowlistAssociate/main.tf b/example/vedbMysqlAllowlistAssociate/main.tf new file mode 100644 index 00000000..c79063cf --- /dev/null +++ b/example/vedbMysqlAllowlistAssociate/main.tf @@ -0,0 +1,47 @@ +resource "volcengine_vedb_mysql_allowlist" "foo" { + allow_list_name = "acc-test-allowlist" + allow_list_desc = "acc-test" + allow_list_type = "IPv4" + allow_list = ["192.168.0.0/24", "192.168.1.0/24", "192.168.2.0/24"] +} + +data "volcengine_zones" "foo"{ +} + +resource "volcengine_vpc" "foo" { + vpc_name = "acc-test-vpc" + cidr_block = "172.16.0.0/16" +} + +resource "volcengine_subnet" "foo" { + subnet_name = "acc-test-subnet" + cidr_block = "172.16.0.0/24" + zone_id = data.volcengine_zones.foo.zones[2].id + vpc_id = volcengine_vpc.foo.id +} + + +resource "volcengine_vedb_mysql_instance" "foo" { + charge_type = "PostPaid" + storage_charge_type = "PostPaid" + db_engine_version = "MySQL_8_0" + db_minor_version = "3.0" + node_number = 2 + node_spec = "vedb.mysql.x4.large" + subnet_id = volcengine_subnet.foo.id + instance_name = "tf-test" + project_name = "testA" + tags { + key = "tftest" + value = "tftest" + } + tags { + key = "tftest2" + value = "tftest2" + } +} + +resource "volcengine_vedb_mysql_allowlist_associate" "foo" { + allow_list_id = volcengine_vedb_mysql_allowlist.foo.id + instance_id = volcengine_vedb_mysql_instance.foo.id +} \ No newline at end of file diff --git a/example/vedbMysqlBackup/main.tf b/example/vedbMysqlBackup/main.tf new file mode 100644 index 00000000..abe67c46 --- /dev/null +++ b/example/vedbMysqlBackup/main.tf @@ -0,0 +1,44 @@ +data "volcengine_zones" "foo"{ +} + +resource "volcengine_vpc" "foo" { + vpc_name = "acc-test-vpc" + cidr_block = "172.16.0.0/16" +} + +resource "volcengine_subnet" "foo" { + subnet_name = "acc-test-subnet" + cidr_block = "172.16.0.0/24" + zone_id = data.volcengine_zones.foo.zones[2].id + vpc_id = volcengine_vpc.foo.id +} + + +resource "volcengine_vedb_mysql_instance" "foo" { + charge_type = "PostPaid" + storage_charge_type = "PostPaid" + db_engine_version = "MySQL_8_0" + db_minor_version = "3.0" + node_number = 2 + node_spec = "vedb.mysql.x4.large" + subnet_id = volcengine_subnet.foo.id + instance_name = "tf-test" + project_name = "testA" + tags { + key = "tftest" + value = "tftest" + } + tags { + key = "tftest2" + value = "tftest2" + } +} + +resource "volcengine_vedb_mysql_backup" "foo" { + instance_id = volcengine_vedb_mysql_instance.foo.id + backup_policy { + backup_time = "18:00Z-20:00Z" + full_backup_period = "Monday,Tuesday,Wednesday" + backup_retention_period = 8 + } +} \ No newline at end of file diff --git a/example/vedbMysqlDatabase/main.tf b/example/vedbMysqlDatabase/main.tf new file mode 100644 index 00000000..cc220ade --- /dev/null +++ b/example/vedbMysqlDatabase/main.tf @@ -0,0 +1,40 @@ +data "volcengine_zones" "foo"{ +} + +resource "volcengine_vpc" "foo" { + vpc_name = "acc-test-vpc" + cidr_block = "172.16.0.0/16" +} + +resource "volcengine_subnet" "foo" { + subnet_name = "acc-test-subnet" + cidr_block = "172.16.0.0/24" + zone_id = data.volcengine_zones.foo.zones[2].id + vpc_id = volcengine_vpc.foo.id +} + + +resource "volcengine_vedb_mysql_instance" "foo" { + charge_type = "PostPaid" + storage_charge_type = "PostPaid" + db_engine_version = "MySQL_8_0" + db_minor_version = "3.0" + node_number = 2 + node_spec = "vedb.mysql.x4.large" + subnet_id = volcengine_subnet.foo.id + instance_name = "tf-test" + project_name = "testA" + tags { + key = "tftest" + value = "tftest" + } + tags { + key = "tftest2" + value = "tftest2" + } +} + +resource "volcengine_vedb_mysql_database" "foo" { + db_name = "tf-table" + instance_id = volcengine_vedb_mysql_instance.foo.id +} \ No newline at end of file diff --git a/example/vedbMysqlEndpoint/main.tf b/example/vedbMysqlEndpoint/main.tf new file mode 100644 index 00000000..628c37c5 --- /dev/null +++ b/example/vedbMysqlEndpoint/main.tf @@ -0,0 +1,52 @@ +data "volcengine_zones" "foo"{ +} + +resource "volcengine_vpc" "foo" { + vpc_name = "acc-test-vpc" + cidr_block = "172.16.0.0/16" +} + +resource "volcengine_subnet" "foo" { + subnet_name = "acc-test-subnet" + cidr_block = "172.16.0.0/24" + zone_id = data.volcengine_zones.foo.zones[2].id + vpc_id = volcengine_vpc.foo.id +} + + +resource "volcengine_vedb_mysql_instance" "foo" { + charge_type = "PostPaid" + storage_charge_type = "PostPaid" + db_engine_version = "MySQL_8_0" + db_minor_version = "3.0" + node_number = 2 + node_spec = "vedb.mysql.x4.large" + subnet_id = volcengine_subnet.foo.id + instance_name = "tf-test" + project_name = "testA" + tags { + key = "tftest" + value = "tftest" + } + tags { + key = "tftest2" + value = "tftest2" + } +} +data "volcengine_vedb_mysql_instances" "foo"{ + instance_id = volcengine_vedb_mysql_instance.foo.id +} + +resource "volcengine_vedb_mysql_endpoint" "foo" { + endpoint_type = "Custom" + instance_id = volcengine_vedb_mysql_instance.foo.id + node_ids = [data.volcengine_vedb_mysql_instances.foo.instances[0].nodes[0].node_id, data.volcengine_vedb_mysql_instances.foo.instances[0].nodes[1].node_id] + read_write_mode = "ReadWrite" + endpoint_name = "tf-test" + description = "tf test" + master_accept_read_requests = true + distributed_transaction = true + consist_level = "Session" + consist_timeout = 100000 + consist_timeout_action = "ReadMaster" +} \ No newline at end of file diff --git a/example/vedbMysqlEndpointPublicAddress/main.tf b/example/vedbMysqlEndpointPublicAddress/main.tf new file mode 100644 index 00000000..2137700b --- /dev/null +++ b/example/vedbMysqlEndpointPublicAddress/main.tf @@ -0,0 +1,67 @@ +data "volcengine_zones" "foo"{ +} + +resource "volcengine_vpc" "foo" { + vpc_name = "acc-test-vpc" + cidr_block = "172.16.0.0/16" +} + +resource "volcengine_subnet" "foo" { + subnet_name = "acc-test-subnet" + cidr_block = "172.16.0.0/24" + zone_id = data.volcengine_zones.foo.zones[2].id + vpc_id = volcengine_vpc.foo.id +} + + +resource "volcengine_vedb_mysql_instance" "foo" { + charge_type = "PostPaid" + storage_charge_type = "PostPaid" + db_engine_version = "MySQL_8_0" + db_minor_version = "3.0" + node_number = 2 + node_spec = "vedb.mysql.x4.large" + subnet_id = volcengine_subnet.foo.id + instance_name = "tf-test" + project_name = "default" + tags { + key = "tftest" + value = "tftest" + } + tags { + key = "tftest2" + value = "tftest2" + } +} +data "volcengine_vedb_mysql_instances" "foo"{ + instance_id = volcengine_vedb_mysql_instance.foo.id +} + +resource "volcengine_vedb_mysql_endpoint" "foo" { + endpoint_type = "Custom" + instance_id = volcengine_vedb_mysql_instance.foo.id + node_ids = [data.volcengine_vedb_mysql_instances.foo.instances[0].nodes[0].node_id, data.volcengine_vedb_mysql_instances.foo.instances[0].nodes[1].node_id] + read_write_mode = "ReadWrite" + endpoint_name = "tf-test" + description = "tf test" + master_accept_read_requests = true + distributed_transaction = true + consist_level = "Session" + consist_timeout = 100000 + consist_timeout_action = "ReadMaster" +} + +resource "volcengine_eip_address" "foo" { + billing_type = "PostPaidByBandwidth" + bandwidth = 1 + isp = "ChinaUnicom" + name = "acc-eip" + description = "acc-test" + project_name = "default" +} + +resource "volcengine_vedb_mysql_endpoint_public_address" "foo" { + eip_id = volcengine_eip_address.foo.id + endpoint_id = volcengine_vedb_mysql_endpoint.foo.endpoint_id + instance_id = volcengine_vedb_mysql_instance.foo.id +} \ No newline at end of file diff --git a/example/vedbMysqlInstance/main.tf b/example/vedbMysqlInstance/main.tf new file mode 100644 index 00000000..2cbcc03c --- /dev/null +++ b/example/vedbMysqlInstance/main.tf @@ -0,0 +1,31 @@ +data "volcengine_zones" "foo"{ +} + +resource "volcengine_vpc" "foo" { + vpc_name = "acc-test-vpc" + cidr_block = "172.16.0.0/16" +} + +resource "volcengine_subnet" "foo" { + subnet_name = "acc-test-subnet" + cidr_block = "172.16.0.0/24" + zone_id = data.volcengine_zones.foo.zones[2].id + vpc_id = volcengine_vpc.foo.id +} + + +resource "volcengine_vedb_mysql_instance" "foo" { + charge_type = "PostPaid" + storage_charge_type = "PostPaid" + db_engine_version = "MySQL_8_0" + db_minor_version = "3.0" + node_number = 2 + node_spec = "vedb.mysql.x4.large" + subnet_id = volcengine_subnet.foo.id + instance_name = "tf-test" + project_name = "default" + tags { + key = "tftest" + value = "tftest" + } +} \ No newline at end of file diff --git a/volcengine/provider.go b/volcengine/provider.go index e6f7dee2..90e73cb1 100644 --- a/volcengine/provider.go +++ b/volcengine/provider.go @@ -10,6 +10,15 @@ import ( "strings" "time" + "github.com/volcengine/terraform-provider-volcengine/volcengine/vedb_mysql/vedb_mysql_account" + "github.com/volcengine/terraform-provider-volcengine/volcengine/vedb_mysql/vedb_mysql_allowlist" + "github.com/volcengine/terraform-provider-volcengine/volcengine/vedb_mysql/vedb_mysql_allowlist_associate" + "github.com/volcengine/terraform-provider-volcengine/volcengine/vedb_mysql/vedb_mysql_backup" + "github.com/volcengine/terraform-provider-volcengine/volcengine/vedb_mysql/vedb_mysql_database" + "github.com/volcengine/terraform-provider-volcengine/volcengine/vedb_mysql/vedb_mysql_endpoint" + "github.com/volcengine/terraform-provider-volcengine/volcengine/vedb_mysql/vedb_mysql_endpoint_public_address" + "github.com/volcengine/terraform-provider-volcengine/volcengine/vedb_mysql/vedb_mysql_instance" + "github.com/volcengine/terraform-provider-volcengine/volcengine/vepfs/vepfs_file_system" "github.com/volcengine/terraform-provider-volcengine/volcengine/vepfs/vepfs_fileset" "github.com/volcengine/terraform-provider-volcengine/volcengine/vepfs/vepfs_mount_service" @@ -708,6 +717,14 @@ func Provider() terraform.ResourceProvider { "volcengine_vepfs_file_systems": vepfs_file_system.DataSourceVolcengineVepfsFileSystems(), "volcengine_vepfs_mount_services": vepfs_mount_service.DataSourceVolcengineVepfsMountServices(), "volcengine_vepfs_filesets": vepfs_fileset.DataSourceVolcengineVepfsFilesets(), + + // ================ veDB Mysql ================ + "volcengine_vedb_mysql_accounts": vedb_mysql_account.DataSourceVolcengineVedbMysqlAccounts(), + "volcengine_vedb_mysql_allowlists": vedb_mysql_allowlist.DataSourceVolcengineVedbMysqlAllowlists(), + "volcengine_vedb_mysql_backups": vedb_mysql_backup.DataSourceVolcengineVedbMysqlBackups(), + "volcengine_vedb_mysql_databases": vedb_mysql_database.DataSourceVolcengineVedbMysqlDatabases(), + "volcengine_vedb_mysql_endpoints": vedb_mysql_endpoint.DataSourceVolcengineVedbMysqlEndpoints(), + "volcengine_vedb_mysql_instances": vedb_mysql_instance.DataSourceVolcengineVedbMysqlInstances(), }, ResourcesMap: map[string]*schema.Resource{ "volcengine_vpc": vpc.ResourceVolcengineVpc(), @@ -1018,6 +1035,16 @@ func Provider() terraform.ResourceProvider { "volcengine_vepfs_mount_service": vepfs_mount_service.ResourceVolcengineVepfsMountService(), "volcengine_vepfs_mount_service_attachment": vepfs_mount_service_attachment.ResourceVolcengineVepfsMountServiceAttachment(), "volcengine_vepfs_fileset": vepfs_fileset.ResourceVolcengineVepfsFileset(), + + // ================ veDB Mysql ================ + "volcengine_vedb_mysql_account": vedb_mysql_account.ResourceVolcengineVedbMysqlAccount(), + "volcengine_vedb_mysql_allowlist": vedb_mysql_allowlist.ResourceVolcengineVedbMysqlAllowlist(), + "volcengine_vedb_mysql_backup": vedb_mysql_backup.ResourceVolcengineVedbMysqlBackup(), + "volcengine_vedb_mysql_database": vedb_mysql_database.ResourceVolcengineVedbMysqlDatabase(), + "volcengine_vedb_mysql_endpoint": vedb_mysql_endpoint.ResourceVolcengineVedbMysqlEndpoint(), + "volcengine_vedb_mysql_instance": vedb_mysql_instance.ResourceVolcengineVedbMysqlInstance(), + "volcengine_vedb_mysql_allowlist_associate": vedb_mysql_allowlist_associate.ResourceVolcengineVedbMysqlAllowlistAssociate(), + "volcengine_vedb_mysql_endpoint_public_address": vedb_mysql_endpoint_public_address.ResourceVolcengineVedbMysqlEndpointPublicAddress(), }, ConfigureFunc: ProviderConfigure, } diff --git a/volcengine/redis/instance/data_source_volcengine_redis_instances.go b/volcengine/redis/instance/data_source_volcengine_redis_instances.go index 47e47592..65b5f569 100644 --- a/volcengine/redis/instance/data_source_volcengine_redis_instances.go +++ b/volcengine/redis/instance/data_source_volcengine_redis_instances.go @@ -230,6 +230,16 @@ func DataSourceVolcengineRedisDbInstances() *schema.Resource { Computed: true, Description: "The connection port.", }, + "vip": { + Type: schema.TypeString, + Computed: true, + Description: "The ipv4 address of the connection address.", + }, + "vip_v6": { + Type: schema.TypeString, + Computed: true, + Description: "The ipv6 address of the connection address.", + }, }, }, }, diff --git a/volcengine/redis/instance/service_volcengine_redis_instance.go b/volcengine/redis/instance/service_volcengine_redis_instance.go index 4ba608d3..a078f377 100644 --- a/volcengine/redis/instance/service_volcengine_redis_instance.go +++ b/volcengine/redis/instance/service_volcengine_redis_instance.go @@ -1245,6 +1245,12 @@ func (s *VolcengineRedisDbInstanceService) DatasourceResources(data *schema.Reso "AZ": { TargetField: "az", }, + "VIP": { + TargetField: "vip", + }, + "VIPv6": { + TargetField: "vip_v6", + }, }, } } diff --git a/volcengine/vedb_mysql/vedb_mysql_account/common_volcengine_vedb_mysql_account.go b/volcengine/vedb_mysql/vedb_mysql_account/common_volcengine_vedb_mysql_account.go new file mode 100644 index 00000000..8f04596c --- /dev/null +++ b/volcengine/vedb_mysql/vedb_mysql_account/common_volcengine_vedb_mysql_account.go @@ -0,0 +1,88 @@ +package vedb_mysql_account + +import ( + "bytes" + "fmt" + "reflect" + "sort" + "strings" + + "github.com/hashicorp/terraform-plugin-sdk/helper/hashcode" + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + "github.com/volcengine/terraform-provider-volcengine/logger" +) + +var veDBMysqlAccountImporter = func(data *schema.ResourceData, i interface{}) ([]*schema.ResourceData, error) { + items := strings.Split(data.Id(), ":") + if len(items) != 2 { + return []*schema.ResourceData{data}, fmt.Errorf("import id must split with ':'") + } + if err := data.Set("instance_id", items[0]); err != nil { + return []*schema.ResourceData{data}, err + } + if err := data.Set("account_name", items[1]); err != nil { + return []*schema.ResourceData{data}, err + } + return []*schema.ResourceData{data}, nil +} + +func veDBMysqlAccountPrivilegeHash(v interface{}) int { + if v == nil { + return hashcode.String("") + } + m := v.(map[string]interface{}) + buf := veDBMysqlAccountPrivilegeHashBase(m) + logger.DebugInfo("RdsMysqlAccountPrivilegeHash %s", buf.String()) + return hashcode.String(buf.String()) +} + +func veDBMysqlAccountPrivilegeHashBase(m map[string]interface{}) (buf bytes.Buffer) { + dbName := strings.ToLower(m["db_name"].(string)) + accountPrivilege := strings.ToLower(m["account_privilege"].(string)) + buf.WriteString(fmt.Sprintf("%s-", dbName)) + buf.WriteString(fmt.Sprintf("%s-", accountPrivilege)) + if accountPrivilege == "custom" { + buf.WriteString(fmt.Sprintf("%s-", mappingAndSortAccountPrivilegeStr(strings.ToLower(m["account_privilege_detail"].(string))))) + } + return buf +} + +// mappingAndSortAccountPrivilegeStr RDS account privilege string mapping +func mappingAndSortAccountPrivilegeStr(accountPrivilegeStr string) string { + mappingPrivileges := mappingAccountPrivilegeStr(accountPrivilegeStr) + sort.Strings(mappingPrivileges) + return strings.Join(mappingPrivileges, ",") +} + +func mappingAccountPrivilegeStr(accountPrivilegeStr string) []string { + privileges := strings.Split(accountPrivilegeStr, ",") + mappingPrivileges := make([]string, 0) + for _, privilege := range privileges { + if mappedPrivilege, ok := veDBMysqlAccountPrivilegeStrMapping[privilege]; ok { + mappingPrivileges = append(mappingPrivileges, mappedPrivilege) + } else { + mappingPrivileges = append(mappingPrivileges, privilege) + } + } + return mappingPrivileges +} + +var veDBMysqlAccountPrivilegeStrMapping = map[string]string{ + "create tmp table": "create temporary tables", + "CREATE TMP TABLE": "CREATE TEMPORARY TABLES", +} + +func veDBMysqlAccountPrivilegeStrDiffSuppress(k, old, new string, d *schema.ResourceData) bool { + // 1. get account_privilege + keys := strings.Split(k, ".") + accountPrivilegeKey := fmt.Sprintf("%s.%s.%s", keys[0], keys[1], "account_privilege") + + // 2. if custom, compute if account_privilege_str is changed + deepEqual := false + if d.Get(accountPrivilegeKey).(string) == "Custom" { + oldPrivileges := mappingAccountPrivilegeStr(old) + newPrivileges := mappingAccountPrivilegeStr(new) + deepEqual = reflect.DeepEqual(oldPrivileges, newPrivileges) + } + return d.Get(accountPrivilegeKey) != "Custom" || deepEqual +} diff --git a/volcengine/vedb_mysql/vedb_mysql_account/data_source_volcengine_vedb_mysql_accounts.go b/volcengine/vedb_mysql/vedb_mysql_account/data_source_volcengine_vedb_mysql_accounts.go new file mode 100644 index 00000000..c0dc8e46 --- /dev/null +++ b/volcengine/vedb_mysql/vedb_mysql_account/data_source_volcengine_vedb_mysql_accounts.go @@ -0,0 +1,89 @@ +package vedb_mysql_account + +import ( + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/helper/validation" + ve "github.com/volcengine/terraform-provider-volcengine/common" +) + +func DataSourceVolcengineVedbMysqlAccounts() *schema.Resource { + return &schema.Resource{ + Read: dataSourceVolcengineVedbMysqlAccountsRead, + Schema: map[string]*schema.Schema{ + "instance_id": { + Type: schema.TypeString, + Required: true, + Description: "The id of the veDB Mysql instance.", + }, + "account_name": { + Type: schema.TypeString, + Optional: true, + Description: "The name of the database account. This field supports fuzzy query.", + }, + "name_regex": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.StringIsValidRegExp, + Description: "A Name Regex of Resource.", + }, + "output_file": { + Type: schema.TypeString, + Optional: true, + Description: "File name where to save data source results.", + }, + "total_count": { + Type: schema.TypeInt, + Computed: true, + Description: "The total count of query.", + }, + "accounts": { + Description: "The collection of query.", + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "account_name": { + Type: schema.TypeString, + Computed: true, + Description: "The name of the database account.", + }, + "account_type": { + Type: schema.TypeString, + Computed: true, + Description: "The type of the database account.", + }, + "account_privileges": { + Type: schema.TypeList, + Computed: true, + Description: "The privilege detail list of RDS mysql instance account.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "db_name": { + Type: schema.TypeString, + Computed: true, + Description: "The name of database.", + }, + "account_privilege": { + Type: schema.TypeString, + Computed: true, + Description: "The privilege type of the account.", + }, + "account_privilege_detail": { + Type: schema.TypeString, + Computed: true, + Description: "The privilege detail of the account.", + }, + }, + }, + }, + }, + }, + }, + }, + } +} + +func dataSourceVolcengineVedbMysqlAccountsRead(d *schema.ResourceData, meta interface{}) error { + service := NewVedbMysqlAccountService(meta.(*ve.SdkClient)) + return service.Dispatcher.Data(service, d, DataSourceVolcengineVedbMysqlAccounts()) +} diff --git a/volcengine/vedb_mysql/vedb_mysql_account/resource_volcengine_vedb_mysql_account.go b/volcengine/vedb_mysql/vedb_mysql_account/resource_volcengine_vedb_mysql_account.go new file mode 100644 index 00000000..c64452f1 --- /dev/null +++ b/volcengine/vedb_mysql/vedb_mysql_account/resource_volcengine_vedb_mysql_account.go @@ -0,0 +1,172 @@ +package vedb_mysql_account + +import ( + "fmt" + "time" + + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + ve "github.com/volcengine/terraform-provider-volcengine/common" +) + +/* + +Import +VedbMysqlAccount can be imported using the instance id and account name, e.g. +``` +$ terraform import volcengine_vedb_mysql_account.default vedbm-r3xq0zdl****:testuser + +``` + +*/ + +func ResourceVolcengineVedbMysqlAccount() *schema.Resource { + resource := &schema.Resource{ + Create: resourceVolcengineVedbMysqlAccountCreate, + Read: resourceVolcengineVedbMysqlAccountRead, + Update: resourceVolcengineVedbMysqlAccountUpdate, + Delete: resourceVolcengineVedbMysqlAccountDelete, + Importer: &schema.ResourceImporter{ + State: veDBMysqlAccountImporter, + }, + Timeouts: &schema.ResourceTimeout{ + Create: schema.DefaultTimeout(30 * time.Minute), + Update: schema.DefaultTimeout(30 * time.Minute), + Delete: schema.DefaultTimeout(30 * time.Minute), + }, + Schema: map[string]*schema.Schema{ + "instance_id": { + Type: schema.TypeString, + ForceNew: true, + Required: true, + Description: "The id of the instance.", + }, + "account_name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: "Database account name. " + + "The account name must meet the following requirements:\n " + + "The name is unique and within 2 to 32 characters in length.\n " + + "Consists of lowercase letters, numbers, or underscores (_).\n " + + "Starts with a lowercase letter and ends with a letter or number.\n " + + "The name cannot contain certain prohibited words. " + + "For detailed information, please refer to prohibited keywords. " + + "And certain reserved words such as root, admin, etc. cannot be used.", + }, + "account_password": { + Type: schema.TypeString, + Required: true, + Sensitive: true, + Description: "Password of database account. " + + "The account password must meet the following requirements:\n " + + "It can only contain upper and lower case letters, numbers and the following special characters _#!@$%^&*()+=-. " + + "\nIt must be within 8 to 32 characters in length.\n " + + "It must contain at least three of upper case letters, lower case letters, numbers or special characters.", + }, + "account_type": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: "Database account type. Values: " + + "\nSuper: High-privilege account. " + + "Only one high-privilege account can be created for an instance." + + " It has all permissions for all databases under this instance and can manage all ordinary accounts and databases. " + + "\nNormal: Multiple ordinary accounts can be created for an instance. " + + "Specific database permissions need to be manually granted to ordinary accounts.", + }, + "account_privileges": { + Type: schema.TypeSet, + Optional: true, + Set: veDBMysqlAccountPrivilegeHash, + DiffSuppressFunc: func(k, old, new string, d *schema.ResourceData) bool { + if d.Get("account_type") == "Super" { + return true + } + return false + }, + Description: "Database permission information. " + + "When the value of AccountType is Super, this parameter does not need to be passed." + + " High-privilege accounts by default have all permissions for all databases under this instance. " + + "When the value of AccountType is Normal, " + + "it is recommended to pass this parameter to grant specified permissions for specified databases to ordinary accounts. " + + "If not set, this account does not have any permissions for any database.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "db_name": { + Type: schema.TypeString, + Required: true, + Description: "Database name requiring authorization.", + }, + "account_privilege": { + Type: schema.TypeString, + Required: true, + Description: "Authorization database privilege types: " + + "\nReadWrite: Read and write privilege.\n " + + "ReadOnly: Read-only privilege.\n " + + "DDLOnly: Only DDL privilege.\n " + + "DMLOnly: Only DML privilege.\n " + + "Custom: Custom privilege.", + }, + // 看下非custom的情况下能不能传detail,如果接口允许传那么得在before call里拦截一下,要不闭环不了 + /* + 在 DescribeDatabases 接口中作为返回参数时,无论 AccountPrivilege 取什么值,都返回该权限类型所包含的 SQL 操作权限详情。 + */ + "account_privilege_detail": { + Type: schema.TypeString, + Optional: true, + Computed: true, + DiffSuppressFunc: veDBMysqlAccountPrivilegeStrDiffSuppress, + Description: "The specific SQL operation permissions contained in the permission type are separated by English commas (,) between multiple strings.\n " + + "When used as a request parameter in the CreateDatabase interface, " + + "when the AccountPrivilege value is Custom, this parameter is required. " + + "Value range (multiple selections allowed): SELECT, INSERT, UPDATE, DELETE," + + " CREATE, DROP, REFERENCES, INDEX, ALTER, CREATE TEMPORARY TABLES, LOCK TABLES, " + + "EXECUTE, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, EVENT, TRIGGER. " + + "When used as a return parameter in the DescribeDatabases interface, " + + "regardless of the value of AccountPrivilege, the details of the SQL operation permissions contained in this permission type are returned. " + + "For the specific SQL operation permissions contained in each permission type, " + + "please refer to the account permission list.", + }, + }, + }, + }, + }, + } + return resource +} + +func resourceVolcengineVedbMysqlAccountCreate(d *schema.ResourceData, meta interface{}) (err error) { + service := NewVedbMysqlAccountService(meta.(*ve.SdkClient)) + err = service.Dispatcher.Create(service, d, ResourceVolcengineVedbMysqlAccount()) + if err != nil { + return fmt.Errorf("error on creating vedb_mysql_account %q, %s", d.Id(), err) + } + return resourceVolcengineVedbMysqlAccountRead(d, meta) +} + +func resourceVolcengineVedbMysqlAccountRead(d *schema.ResourceData, meta interface{}) (err error) { + service := NewVedbMysqlAccountService(meta.(*ve.SdkClient)) + err = service.Dispatcher.Read(service, d, ResourceVolcengineVedbMysqlAccount()) + if err != nil { + return fmt.Errorf("error on reading vedb_mysql_account %q, %s", d.Id(), err) + } + return err +} + +func resourceVolcengineVedbMysqlAccountUpdate(d *schema.ResourceData, meta interface{}) (err error) { + service := NewVedbMysqlAccountService(meta.(*ve.SdkClient)) + err = service.Dispatcher.Update(service, d, ResourceVolcengineVedbMysqlAccount()) + if err != nil { + return fmt.Errorf("error on updating vedb_mysql_account %q, %s", d.Id(), err) + } + return resourceVolcengineVedbMysqlAccountRead(d, meta) +} + +func resourceVolcengineVedbMysqlAccountDelete(d *schema.ResourceData, meta interface{}) (err error) { + service := NewVedbMysqlAccountService(meta.(*ve.SdkClient)) + err = service.Dispatcher.Delete(service, d, ResourceVolcengineVedbMysqlAccount()) + if err != nil { + return fmt.Errorf("error on deleting vedb_mysql_account %q, %s", d.Id(), err) + } + return err +} diff --git a/volcengine/vedb_mysql/vedb_mysql_account/service_volcengine_vedb_mysql_account.go b/volcengine/vedb_mysql/vedb_mysql_account/service_volcengine_vedb_mysql_account.go new file mode 100644 index 00000000..760cf992 --- /dev/null +++ b/volcengine/vedb_mysql/vedb_mysql_account/service_volcengine_vedb_mysql_account.go @@ -0,0 +1,387 @@ +package vedb_mysql_account + +import ( + "encoding/json" + "errors" + "fmt" + "strings" + "time" + + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + ve "github.com/volcengine/terraform-provider-volcengine/common" + "github.com/volcengine/terraform-provider-volcengine/logger" + "github.com/volcengine/terraform-provider-volcengine/volcengine/vedb_mysql/vedb_mysql_database" +) + +type VolcengineVedbMysqlAccountService struct { + Client *ve.SdkClient + Dispatcher *ve.Dispatcher +} + +func NewVedbMysqlAccountService(c *ve.SdkClient) *VolcengineVedbMysqlAccountService { + return &VolcengineVedbMysqlAccountService{ + Client: c, + Dispatcher: &ve.Dispatcher{}, + } +} + +func (s *VolcengineVedbMysqlAccountService) GetClient() *ve.SdkClient { + return s.Client +} + +func (s *VolcengineVedbMysqlAccountService) ReadResources(m map[string]interface{}) (data []interface{}, err error) { + var ( + resp *map[string]interface{} + results interface{} + ok bool + ) + return ve.WithPageNumberQuery(m, "PageSize", "PageNumber", 100, 1, func(condition map[string]interface{}) ([]interface{}, error) { + universalClient := s.Client.UniversalClient + action := "DescribeDBAccounts" + logger.Debug(logger.ReqFormat, action, condition) + if condition == nil { + resp, err = universalClient.DoCall(getUniversalInfo(action), nil) + if err != nil { + return data, err + } + } else { + resp, err = universalClient.DoCall(getUniversalInfo(action), &condition) + if err != nil { + return data, err + } + } + respBytes, _ := json.Marshal(resp) + logger.Debug(logger.RespFormat, action, condition, string(respBytes)) + results, err = ve.ObtainSdkValue("Result.Accounts", *resp) + if err != nil { + return data, err + } + if results == nil { + results = []interface{}{} + } + if data, ok = results.([]interface{}); !ok { + return data, errors.New("Result.Accounts is not Slice") + } + return data, err + }) +} + +func (s *VolcengineVedbMysqlAccountService) ReadResource(resourceData *schema.ResourceData, id string) (data map[string]interface{}, err error) { + var ( + results []interface{} + account map[string]interface{} + ok bool + ) + if id == "" { + id = s.ReadResourceId(resourceData.Id()) + } + ids := strings.Split(id, ":") + if len(ids) != 2 { + return map[string]interface{}{}, fmt.Errorf("invalid veDB mysql account id") + } + + instanceId := ids[0] + accountName := ids[1] + + req := map[string]interface{}{ + "InstanceId": instanceId, + "AccountName": accountName, + } + results, err = s.ReadResources(req) + if err != nil { + return data, err + } + + for _, r := range results { + account, ok = r.(map[string]interface{}) + if !ok { + return data, errors.New("Value is not map ") + } + if accountName == account["AccountName"].(string) { + data = account + break + } + } + + if len(data) == 0 { + return data, fmt.Errorf("veDB account %s not exist ", id) + } + + return data, err +} + +func (s *VolcengineVedbMysqlAccountService) RefreshResourceState(resourceData *schema.ResourceData, target []string, timeout time.Duration, id string) *resource.StateChangeConf { + return &resource.StateChangeConf{ + Pending: []string{}, + Delay: 1 * time.Second, + MinTimeout: 1 * time.Second, + Target: target, + Timeout: timeout, + Refresh: func() (result interface{}, state string, err error) { + var ( + d map[string]interface{} + status interface{} + failStates []string + ) + failStates = append(failStates, "Failed") + d, err = s.ReadResource(resourceData, id) + if err != nil { + return nil, "", err + } + status, err = ve.ObtainSdkValue("Status", d) + if err != nil { + return nil, "", err + } + for _, v := range failStates { + if v == status.(string) { + return nil, "", fmt.Errorf("vedb_mysql_account status error, status: %s", status.(string)) + } + } + return d, status.(string), err + }, + } +} + +func (s *VolcengineVedbMysqlAccountService) CreateResource(resourceData *schema.ResourceData, resource *schema.Resource) []ve.Callback { + callback := ve.Callback{ + Call: ve.SdkCall{ + Action: "CreateDBAccount", + ConvertMode: ve.RequestConvertAll, + Convert: map[string]ve.RequestConvert{ + "account_privileges": { + TargetField: "AccountPrivileges", + ConvertType: ve.ConvertJsonObjectArray, + NextLevelConvert: map[string]ve.RequestConvert{ + "db_name": { + TargetField: "DBName", + }, + }, + }, + }, + ContentType: ve.ContentTypeJson, + BeforeCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (bool, error) { + privileges := d.Get("account_privileges") + if privileges == nil || privileges.(*schema.Set).Len() == 0 { + return true, nil + } + for _, privilege := range privileges.(*schema.Set).List() { + privilegeMap, ok := privilege.(map[string]interface{}) + if !ok { + return false, fmt.Errorf("account_privilege is not map") + } + id := fmt.Sprintf("%s:%s", d.Get("instance_id"), privilegeMap["db_name"]) + _, err := vedb_mysql_database.NewVedbMysqlDatabaseService(client).ReadResource(d, id) + if err != nil { + return false, err + } + } + return true, nil + }, + ExecuteCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (*map[string]interface{}, error) { + logger.Debug(logger.ReqFormat, call.Action, call.SdkParam) + return s.Client.UniversalClient.DoCall(getUniversalInfo(call.Action), call.SdkParam) + }, + AfterCall: func(d *schema.ResourceData, client *ve.SdkClient, resp *map[string]interface{}, call ve.SdkCall) error { + id := fmt.Sprintf("%s:%s", d.Get("instance_id"), d.Get("account_name")) + d.SetId(id) + return nil + }, + }, + } + return []ve.Callback{callback} +} + +func (VolcengineVedbMysqlAccountService) WithResourceResponseHandlers(d map[string]interface{}) []ve.ResourceResponseHandler { + handler := func() (map[string]interface{}, map[string]ve.ResponseConvert, error) { + return d, map[string]ve.ResponseConvert{ + "DBName": { + TargetField: "db_name", + }, + }, nil + } + return []ve.ResourceResponseHandler{handler} +} + +func (s *VolcengineVedbMysqlAccountService) ModifyResource(resourceData *schema.ResourceData, resource *schema.Resource) []ve.Callback { + var callbacks []ve.Callback + if resourceData.HasChange("account_password") { + callback := ve.Callback{ + Call: ve.SdkCall{ + Action: "ResetDBAccount", + ConvertMode: ve.RequestConvertIgnore, + SdkParam: &map[string]interface{}{ + "InstanceId": resourceData.Get("instance_id"), + "AccountName": resourceData.Get("account_name"), + "AccountPassword": resourceData.Get("account_password"), + }, + ExecuteCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (*map[string]interface{}, error) { + logger.Debug(logger.ReqFormat, call.Action, call.SdkParam) + return s.Client.UniversalClient.DoCall(getUniversalInfo(call.Action), call.SdkParam) + }, + }, + } + callbacks = append(callbacks, callback) + } + if resourceData.HasChange("account_privileges") { + callback := ve.Callback{ + Call: ve.SdkCall{ + Action: "GrantDBAccountPrivilege", + ConvertMode: ve.RequestConvertInConvert, + ContentType: ve.ContentTypeJson, + Convert: map[string]ve.RequestConvert{ + "account_privileges": { + TargetField: "AccountPrivileges", + ForceGet: true, + NextLevelConvert: map[string]ve.RequestConvert{ + "db_name": { + TargetField: "DBName", + }, + }, + ConvertType: ve.ConvertJsonObjectArray, + }, + }, + BeforeCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (bool, error) { + (*call.SdkParam)["InstanceId"] = d.Get("instance_id") + (*call.SdkParam)["AccountName"] = d.Get("account_name") + return true, nil + }, + ExecuteCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (*map[string]interface{}, error) { + logger.Debug(logger.ReqFormat, call.Action, call.SdkParam) + return s.Client.UniversalClient.DoCall(getUniversalInfo(call.Action), call.SdkParam) + }, + }, + } + callbacks = append(callbacks, callback) + + add, remove, _, _ := ve.GetSetDifference("account_privileges", resourceData, veDBMysqlAccountPrivilegeHash, false) + if remove != nil && remove.Len() > 0 { + removeCallback := ve.Callback{ + Call: ve.SdkCall{ + Action: "RevokeDBAccountPrivilege", + ConvertMode: ve.RequestConvertIgnore, + BeforeCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (bool, error) { + (*call.SdkParam)["InstanceId"] = d.Get("instance_id") + (*call.SdkParam)["AccountName"] = d.Get("account_name") + dbNames := make([]string, 0) + for _, item := range remove.List() { + m, ok := item.(map[string]interface{}) + if !ok { + continue + } + removeDbName := m["db_name"].(string) + // 过滤掉有Grant操作的db_name,Grant权限方式为覆盖,先取消原有权限,再赋新权限,此处无需再取消一次。 + if add != nil && add.Len() > 0 && hasDbNameInSet(removeDbName, add) { + continue + } + dbNames = append(dbNames, removeDbName) + } + if len(dbNames) == 0 { + return false, nil + } + (*call.SdkParam)["DBNames"] = strings.Join(dbNames, ",") + return true, nil + }, + ExecuteCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (*map[string]interface{}, error) { + logger.Debug(logger.ReqFormat, call.Action, call.SdkParam) + return s.Client.UniversalClient.DoCall(getUniversalInfo(call.Action), call.SdkParam) + }, + }, + } + callbacks = append(callbacks, removeCallback) + } + } + return callbacks +} + +func hasDbNameInSet(dbName string, set *schema.Set) bool { + for _, item := range set.List() { + if m, ok := item.(map[string]interface{}); ok { + if v, ok := m["db_name"]; ok && v.(string) == dbName { + if detail, ok := m["account_privilege_detail"].(string); ok { + if len(detail) == 0 { + return false + } + } else { + return false + } + return true + } + } + } + return false +} + +func (s *VolcengineVedbMysqlAccountService) RemoveResource(resourceData *schema.ResourceData, r *schema.Resource) []ve.Callback { + callback := ve.Callback{ + Call: ve.SdkCall{ + Action: "DeleteDBAccount", + ContentType: ve.ContentTypeJson, + ConvertMode: ve.RequestConvertIgnore, + BeforeCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (bool, error) { + rdsAccountId := d.Id() + ids := strings.Split(rdsAccountId, ":") + if len(ids) != 2 { + return false, fmt.Errorf("invalid veDB mysql account id") + } + (*call.SdkParam)["InstanceId"] = ids[0] + (*call.SdkParam)["AccountName"] = ids[1] + return true, nil + }, + ExecuteCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (*map[string]interface{}, error) { + logger.Debug(logger.ReqFormat, call.Action, call.SdkParam) + //删除RdsMysqlAccount + return s.Client.UniversalClient.DoCall(getUniversalInfo(call.Action), call.SdkParam) + }, + LockId: func(d *schema.ResourceData) string { + return d.Get("instance_id").(string) + }, + CallError: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall, baseErr error) error { + //出现错误后重试 + return resource.Retry(15*time.Minute, func() *resource.RetryError { + _, callErr := s.ReadResource(d, "") + if callErr != nil { + if ve.ResourceNotFoundError(callErr) { + return nil + } else { + return resource.NonRetryableError(fmt.Errorf("error on reading veDB mysql account on delete %q, %w", d.Id(), callErr)) + } + } + _, callErr = call.ExecuteCall(d, client, call) + if callErr == nil { + return nil + } + return resource.RetryableError(callErr) + }) + }, + }, + } + return []ve.Callback{callback} +} + +func (s *VolcengineVedbMysqlAccountService) DatasourceResources(*schema.ResourceData, *schema.Resource) ve.DataSourceInfo { + return ve.DataSourceInfo{ + NameField: "AccountName", + CollectField: "accounts", + ContentType: ve.ContentTypeJson, + ResponseConverts: map[string]ve.ResponseConvert{ + "DBName": { + TargetField: "db_name", + }, + }, + } +} + +func (s *VolcengineVedbMysqlAccountService) ReadResourceId(id string) string { + return id +} + +func getUniversalInfo(actionName string) ve.UniversalInfo { + return ve.UniversalInfo{ + ServiceName: "vedbm", + Version: "2022-01-01", + HttpMethod: ve.POST, + ContentType: ve.ApplicationJSON, + Action: actionName, + } +} diff --git a/volcengine/vedb_mysql/vedb_mysql_allowlist/data_source_volcengine_vedb_mysql_allowlists.go b/volcengine/vedb_mysql/vedb_mysql_allowlist/data_source_volcengine_vedb_mysql_allowlists.go new file mode 100644 index 00000000..a6eaaa09 --- /dev/null +++ b/volcengine/vedb_mysql/vedb_mysql_allowlist/data_source_volcengine_vedb_mysql_allowlists.go @@ -0,0 +1,117 @@ +package vedb_mysql_allowlist + +import ( + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/helper/validation" + ve "github.com/volcengine/terraform-provider-volcengine/common" +) + +func DataSourceVolcengineVedbMysqlAllowlists() *schema.Resource { + return &schema.Resource{ + Read: dataSourceVolcengineVedbMysqlAllowlistsRead, + Schema: map[string]*schema.Schema{ + "region_id": { + Required: true, + Type: schema.TypeString, + Description: "The region of the allow lists.", + }, + "instance_id": { + Type: schema.TypeString, + Optional: true, + Description: "Instance ID. When an InstanceId is specified, the DescribeAllowLists interface will return the whitelist bound to the specified instance.", + }, + "name_regex": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.StringIsValidRegExp, + Description: "A Name Regex of Resource.", + }, + "output_file": { + Type: schema.TypeString, + Optional: true, + Description: "File name where to save data source results.", + }, + "total_count": { + Type: schema.TypeInt, + Computed: true, + Description: "The total count of query.", + }, + "allow_lists": { + Description: "The collection of query.", + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "allow_list_desc": { + Type: schema.TypeString, + Computed: true, + Description: "The description of the allow list.", + }, + "allow_list_id": { + Type: schema.TypeString, + Computed: true, + Description: "The id of the allow list.", + }, + "allow_list_name": { + Type: schema.TypeString, + Computed: true, + Description: "The name of the allow list.", + }, + "allow_list_ip_num": { + Type: schema.TypeInt, + Computed: true, + Description: "The total number of IP addresses (or address ranges) in the whitelist.", + }, + "allow_list_type": { + Type: schema.TypeString, + Computed: true, + Description: "The type of the allow list.", + }, + "associated_instance_num": { + Type: schema.TypeInt, + Computed: true, + Description: "The total number of instances bound under the whitelist.", + }, + "allow_list": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + Description: "The IP address or a range of IP addresses in CIDR format.", + }, + "associated_instances": { + Type: schema.TypeList, + Computed: true, + Description: "The list of instances.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "instance_id": { + Type: schema.TypeString, + Computed: true, + Description: "The id of the instance.", + }, + "instance_name": { + Type: schema.TypeString, + Computed: true, + Description: "The name of the instance.", + }, + "vpc": { + Type: schema.TypeString, + Computed: true, + Description: "The id of the vpc.", + }, + }, + }, + }, + }, + }, + }, + }, + } +} + +func dataSourceVolcengineVedbMysqlAllowlistsRead(d *schema.ResourceData, meta interface{}) error { + service := NewVedbMysqlAllowlistService(meta.(*ve.SdkClient)) + return service.Dispatcher.Data(service, d, DataSourceVolcengineVedbMysqlAllowlists()) +} diff --git a/volcengine/vedb_mysql/vedb_mysql_allowlist/resource_volcengine_vedb_mysql_allowlist.go b/volcengine/vedb_mysql/vedb_mysql_allowlist/resource_volcengine_vedb_mysql_allowlist.go new file mode 100644 index 00000000..551fd6e1 --- /dev/null +++ b/volcengine/vedb_mysql/vedb_mysql_allowlist/resource_volcengine_vedb_mysql_allowlist.go @@ -0,0 +1,105 @@ +package vedb_mysql_allowlist + +import ( + "fmt" + "time" + + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + ve "github.com/volcengine/terraform-provider-volcengine/common" +) + +/* + +Import +VedbMysqlAllowlist can be imported using the id, e.g. +``` +$ terraform import volcengine_vedb_mysql_allowlist.default resource_id +``` + +*/ + +func ResourceVolcengineVedbMysqlAllowlist() *schema.Resource { + resource := &schema.Resource{ + Create: resourceVolcengineVedbMysqlAllowlistCreate, + Read: resourceVolcengineVedbMysqlAllowlistRead, + Update: resourceVolcengineVedbMysqlAllowlistUpdate, + Delete: resourceVolcengineVedbMysqlAllowlistDelete, + Importer: &schema.ResourceImporter{ + State: schema.ImportStatePassthrough, + }, + Timeouts: &schema.ResourceTimeout{ + Create: schema.DefaultTimeout(30 * time.Minute), + Update: schema.DefaultTimeout(30 * time.Minute), + Delete: schema.DefaultTimeout(30 * time.Minute), + }, + Schema: map[string]*schema.Schema{ + "allow_list_name": { + Type: schema.TypeString, + Required: true, + Description: "The name of the allow list.", + }, + "allow_list_desc": { + Type: schema.TypeString, + Optional: true, + Description: "The description of the allow list.", + }, + "allow_list_type": { + Type: schema.TypeString, + Optional: true, + Computed: true, + Description: "The type of IP address in the whitelist. Currently only IPv4 addresses are supported.", + }, + "allow_list": { + Type: schema.TypeSet, + Required: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + Set: schema.HashString, + Description: "Enter an IP address or a range of IP addresses in CIDR format.", + }, + "allow_list_id": { + Type: schema.TypeString, + Computed: true, + Description: "The id of the allow list.", + }, + }, + } + return resource +} + +func resourceVolcengineVedbMysqlAllowlistCreate(d *schema.ResourceData, meta interface{}) (err error) { + service := NewVedbMysqlAllowlistService(meta.(*ve.SdkClient)) + err = service.Dispatcher.Create(service, d, ResourceVolcengineVedbMysqlAllowlist()) + if err != nil { + return fmt.Errorf("error on creating vedb_mysql_allowlist %q, %s", d.Id(), err) + } + return resourceVolcengineVedbMysqlAllowlistRead(d, meta) +} + +func resourceVolcengineVedbMysqlAllowlistRead(d *schema.ResourceData, meta interface{}) (err error) { + service := NewVedbMysqlAllowlistService(meta.(*ve.SdkClient)) + err = service.Dispatcher.Read(service, d, ResourceVolcengineVedbMysqlAllowlist()) + if err != nil { + return fmt.Errorf("error on reading vedb_mysql_allowlist %q, %s", d.Id(), err) + } + return err +} + +func resourceVolcengineVedbMysqlAllowlistUpdate(d *schema.ResourceData, meta interface{}) (err error) { + service := NewVedbMysqlAllowlistService(meta.(*ve.SdkClient)) + err = service.Dispatcher.Update(service, d, ResourceVolcengineVedbMysqlAllowlist()) + if err != nil { + return fmt.Errorf("error on updating vedb_mysql_allowlist %q, %s", d.Id(), err) + } + return resourceVolcengineVedbMysqlAllowlistRead(d, meta) +} + +func resourceVolcengineVedbMysqlAllowlistDelete(d *schema.ResourceData, meta interface{}) (err error) { + service := NewVedbMysqlAllowlistService(meta.(*ve.SdkClient)) + err = service.Dispatcher.Delete(service, d, ResourceVolcengineVedbMysqlAllowlist()) + if err != nil { + return fmt.Errorf("error on deleting vedb_mysql_allowlist %q, %s", d.Id(), err) + } + return err +} diff --git a/volcengine/vedb_mysql/vedb_mysql_allowlist/service_volcengine_vedb_mysql_allowlist.go b/volcengine/vedb_mysql/vedb_mysql_allowlist/service_volcengine_vedb_mysql_allowlist.go new file mode 100644 index 00000000..fa0e62ac --- /dev/null +++ b/volcengine/vedb_mysql/vedb_mysql_allowlist/service_volcengine_vedb_mysql_allowlist.go @@ -0,0 +1,303 @@ +package vedb_mysql_allowlist + +import ( + "errors" + "fmt" + "strings" + "time" + + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + ve "github.com/volcengine/terraform-provider-volcengine/common" + "github.com/volcengine/terraform-provider-volcengine/logger" +) + +type VolcengineVedbMysqlAllowlistService struct { + Client *ve.SdkClient + Dispatcher *ve.Dispatcher +} + +func NewVedbMysqlAllowlistService(c *ve.SdkClient) *VolcengineVedbMysqlAllowlistService { + return &VolcengineVedbMysqlAllowlistService{ + Client: c, + Dispatcher: &ve.Dispatcher{}, + } +} + +func (s *VolcengineVedbMysqlAllowlistService) GetClient() *ve.SdkClient { + return s.Client +} + +func (s *VolcengineVedbMysqlAllowlistService) ReadResources(condition map[string]interface{}) (data []interface{}, err error) { + var ( + resp *map[string]interface{} + results interface{} + ok bool + allowListId string + ) + return ve.WithSimpleQuery(condition, func(m map[string]interface{}) ([]interface{}, error) { + action := "DescribeAllowLists" + logger.Debug(logger.ReqFormat, action, condition) + if condition == nil { + resp, err = s.Client.UniversalClient.DoCall(getUniversalInfo(action), nil) + if err != nil { + return data, err + } + } else { + resp, err = s.Client.UniversalClient.DoCall(getUniversalInfo(action), &condition) + if err != nil { + return data, err + } + } + results, err = ve.ObtainSdkValue("Result.AllowLists", *resp) + if err != nil { + return data, err + } + if results == nil { + results = []interface{}{} + } + if data, ok = results.([]interface{}); !ok { + return data, errors.New("Result.AllowLists is not slice ") + } + + if id, exist := condition["AllowListId"]; exist { + allowListId = id.(string) + } + for index, ele := range data { + allowList := ele.(map[string]interface{}) + + if allowListId == "" || allowListId == allowList["AllowListId"].(string) { + query := map[string]interface{}{ + "AllowListId": allowList["AllowListId"], + } + action = "DescribeAllowListDetail" + logger.Debug(logger.ReqFormat, action, query) + resp, err = s.Client.UniversalClient.DoCall(getUniversalInfo(action), &query) + if err != nil { + return data, err + } + logger.Debug(logger.RespFormat, action, query, *resp) + instances, err := ve.ObtainSdkValue("Result.AssociatedInstances", *resp) + if err != nil { + return data, err + } + data[index].(map[string]interface{})["AssociatedInstances"] = instances + allowListIp, err := ve.ObtainSdkValue("Result.AllowList", *resp) + if err != nil { + return data, err + } + allowListIpArr := strings.Split(allowListIp.(string), ",") + data[index].(map[string]interface{})["AllowList"] = allowListIpArr + } + } + return data, err + }) +} + +func (s *VolcengineVedbMysqlAllowlistService) ReadResource(resourceData *schema.ResourceData, id string) (data map[string]interface{}, err error) { + var ( + results []interface{} + ) + if id == "" { + id = s.ReadResourceId(resourceData.Id()) + } + req := map[string]interface{}{ + "RegionId": s.Client.Region, + "AllowListId": id, + } + results, err = s.ReadResources(req) + if err != nil { + return data, err + } + for _, v := range results { + result, ok := v.(map[string]interface{}) + if !ok { + return data, errors.New("Value is not map ") + } + if result["AllowListId"].(string) == id { + data = result + break + } + } + if len(data) == 0 { + return data, fmt.Errorf("vedb mysql allowlist %s not exist ", id) + } + return data, err +} + +func (s *VolcengineVedbMysqlAllowlistService) RefreshResourceState(resourceData *schema.ResourceData, target []string, timeout time.Duration, id string) *resource.StateChangeConf { + return &resource.StateChangeConf{ + Pending: []string{}, + Delay: 1 * time.Second, + MinTimeout: 1 * time.Second, + Target: target, + Timeout: timeout, + Refresh: func() (result interface{}, state string, err error) { + var ( + d map[string]interface{} + status interface{} + failStates []string + ) + failStates = append(failStates, "Failed") + d, err = s.ReadResource(resourceData, id) + if err != nil { + return nil, "", err + } + status, err = ve.ObtainSdkValue("Status", d) + if err != nil { + return nil, "", err + } + for _, v := range failStates { + if v == status.(string) { + return nil, "", fmt.Errorf("vedb_mysql_allowlist status error, status: %s", status.(string)) + } + } + return d, status.(string), err + }, + } +} + +func (s *VolcengineVedbMysqlAllowlistService) CreateResource(resourceData *schema.ResourceData, resource *schema.Resource) []ve.Callback { + callback := ve.Callback{ + Call: ve.SdkCall{ + Action: "CreateAllowList", + ConvertMode: ve.RequestConvertAll, + ContentType: ve.ContentTypeJson, + Convert: map[string]ve.RequestConvert{ + "allow_list": { + Ignore: true, + }, + }, + BeforeCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (bool, error) { + var allowStrings []string + allowListsSet := d.Get("allow_list").(*schema.Set) + allowLists := allowListsSet.List() + for _, list := range allowLists { + allowStrings = append(allowStrings, list.(string)) + } + lists := strings.Join(allowStrings, ",") + logger.Debug(logger.ReqFormat, call.Action, call.SdkParam, lists) + (*call.SdkParam)["AllowList"] = lists + return true, nil + }, + ExecuteCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (*map[string]interface{}, error) { + logger.Debug(logger.ReqFormat, call.Action, call.SdkParam) + return s.Client.UniversalClient.DoCall(getUniversalInfo(call.Action), call.SdkParam) + }, + AfterCall: func(d *schema.ResourceData, client *ve.SdkClient, resp *map[string]interface{}, call ve.SdkCall) error { + id, _ := ve.ObtainSdkValue("Result.AllowListId", *resp) + d.SetId(id.(string)) + return nil + }, + }, + } + return []ve.Callback{callback} +} + +func (VolcengineVedbMysqlAllowlistService) WithResourceResponseHandlers(d map[string]interface{}) []ve.ResourceResponseHandler { + handler := func() (map[string]interface{}, map[string]ve.ResponseConvert, error) { + return d, nil, nil + } + return []ve.ResourceResponseHandler{handler} +} + +func (s *VolcengineVedbMysqlAllowlistService) ModifyResource(resourceData *schema.ResourceData, resource *schema.Resource) []ve.Callback { + callback := ve.Callback{ + Call: ve.SdkCall{ + Action: "ModifyAllowList", + ConvertMode: ve.RequestConvertInConvert, + ContentType: ve.ContentTypeJson, + Convert: map[string]ve.RequestConvert{ + "allow_list": { + Ignore: true, + }, + "apply_instance_num": { + Ignore: true, + }, + "allow_list_desc": { + ForceGet: true, + }, + }, + BeforeCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (bool, error) { + var allowStrings []string + // 修改allowList必须传ApplyInstanceNum + resp, err := s.ReadResource(d, d.Id()) + if err != nil { + return false, err + } + num := resp["AssociatedInstanceNum"].(float64) + (*call.SdkParam)["ApplyInstanceNum"] = int(num) + allowListsSet := d.Get("allow_list").(*schema.Set) + allowLists := allowListsSet.List() + for _, list := range allowLists { + allowStrings = append(allowStrings, list.(string)) + } + lists := strings.Join(allowStrings, ",") + logger.Debug(logger.ReqFormat, call.Action, call.SdkParam, lists) + (*call.SdkParam)["AllowList"] = lists + return true, nil + }, + SdkParam: &map[string]interface{}{ + "AllowListId": resourceData.Id(), + "AllowListName": resourceData.Get("allow_list_name").(string), + }, + ExecuteCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (*map[string]interface{}, error) { + logger.Debug(logger.ReqFormat, call.Action, call.SdkParam) + return s.Client.UniversalClient.DoCall(getUniversalInfo(call.Action), call.SdkParam) + }, + }, + } + return []ve.Callback{callback} +} + +func (s *VolcengineVedbMysqlAllowlistService) RemoveResource(resourceData *schema.ResourceData, r *schema.Resource) []ve.Callback { + callback := ve.Callback{ + Call: ve.SdkCall{ + Action: "DeleteAllowList", + ConvertMode: ve.RequestConvertIgnore, + ContentType: ve.ContentTypeJson, + SdkParam: &map[string]interface{}{ + "AllowListId": resourceData.Id(), + }, + ExecuteCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (*map[string]interface{}, error) { + logger.Debug(logger.RespFormat, call.Action, call.SdkParam) + return s.Client.UniversalClient.DoCall(getUniversalInfo(call.Action), call.SdkParam) + }, + AfterCall: func(d *schema.ResourceData, client *ve.SdkClient, resp *map[string]interface{}, call ve.SdkCall) error { + return ve.CheckResourceUtilRemoved(d, s.ReadResource, 5*time.Minute) + }, + }, + } + return []ve.Callback{callback} +} + +func (s *VolcengineVedbMysqlAllowlistService) DatasourceResources(*schema.ResourceData, *schema.Resource) ve.DataSourceInfo { + return ve.DataSourceInfo{ + ContentType: ve.ContentTypeJson, + NameField: "AllowListName", + IdField: "AllowListId", + CollectField: "allow_lists", + ResponseConverts: map[string]ve.ResponseConvert{ + "AllowListIPNum": { + TargetField: "allow_list_ip_num", + }, + "VPC": { + TargetField: "vpc", + }, + }, + } +} + +func (s *VolcengineVedbMysqlAllowlistService) ReadResourceId(id string) string { + return id +} + +func getUniversalInfo(actionName string) ve.UniversalInfo { + return ve.UniversalInfo{ + ServiceName: "vedbm", + Version: "2022-01-01", + HttpMethod: ve.POST, + ContentType: ve.ApplicationJSON, + Action: actionName, + } +} diff --git a/volcengine/vedb_mysql/vedb_mysql_allowlist_associate/resource_volcengine_vedb_mysql_allowlist_associate.go b/volcengine/vedb_mysql/vedb_mysql_allowlist_associate/resource_volcengine_vedb_mysql_allowlist_associate.go new file mode 100644 index 00000000..e4b17728 --- /dev/null +++ b/volcengine/vedb_mysql/vedb_mysql_allowlist_associate/resource_volcengine_vedb_mysql_allowlist_associate.go @@ -0,0 +1,94 @@ +package vedb_mysql_allowlist_associate + +import ( + "fmt" + "strings" + "time" + + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + ve "github.com/volcengine/terraform-provider-volcengine/common" +) + +/* + +Import +VedbMysqlAllowlistAssociate can be imported using the instance id and allow list id, e.g. +``` +$ terraform import volcengine_vedb_mysql_allowlist_associate.default vedbm-iqnh3a7z****:acl-d1fd76693bd54e658912e7337d5b**** +``` + +*/ + +func ResourceVolcengineVedbMysqlAllowlistAssociate() *schema.Resource { + resource := &schema.Resource{ + Create: resourceVolcengineVedbMysqlAllowlistAssociateCreate, + Read: resourceVolcengineVedbMysqlAllowlistAssociateRead, + Delete: resourceVolcengineVedbMysqlAllowlistAssociateDelete, + Importer: &schema.ResourceImporter{ + State: importAllowListAssociate, + }, + Timeouts: &schema.ResourceTimeout{ + Create: schema.DefaultTimeout(30 * time.Minute), + Delete: schema.DefaultTimeout(30 * time.Minute), + }, + Schema: map[string]*schema.Schema{ + "instance_id": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: "The id of the mysql instance.", + }, + "allow_list_id": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: "The id of the allow list.", + }, + }, + } + return resource +} + +func resourceVolcengineVedbMysqlAllowlistAssociateCreate(d *schema.ResourceData, meta interface{}) (err error) { + service := NewVedbMysqlAllowlistAssociateService(meta.(*ve.SdkClient)) + err = service.Dispatcher.Create(service, d, ResourceVolcengineVedbMysqlAllowlistAssociate()) + if err != nil { + return fmt.Errorf("error on creating vedb_mysql_allowlist_associate %q, %s", d.Id(), err) + } + return resourceVolcengineVedbMysqlAllowlistAssociateRead(d, meta) +} + +func resourceVolcengineVedbMysqlAllowlistAssociateRead(d *schema.ResourceData, meta interface{}) (err error) { + service := NewVedbMysqlAllowlistAssociateService(meta.(*ve.SdkClient)) + err = service.Dispatcher.Read(service, d, ResourceVolcengineVedbMysqlAllowlistAssociate()) + if err != nil { + return fmt.Errorf("error on reading vedb_mysql_allowlist_associate %q, %s", d.Id(), err) + } + return err +} + +func resourceVolcengineVedbMysqlAllowlistAssociateDelete(d *schema.ResourceData, meta interface{}) (err error) { + service := NewVedbMysqlAllowlistAssociateService(meta.(*ve.SdkClient)) + err = service.Dispatcher.Delete(service, d, ResourceVolcengineVedbMysqlAllowlistAssociate()) + if err != nil { + return fmt.Errorf("error on deleting vedb_mysql_allowlist_associate %q, %s", d.Id(), err) + } + return err +} + +func importAllowListAssociate(data *schema.ResourceData, i interface{}) ([]*schema.ResourceData, error) { + var err error + items := strings.Split(data.Id(), ":") + if len(items) != 2 { + return []*schema.ResourceData{data}, fmt.Errorf("import id must be of the form InstanceId:AllowListId") + } + err = data.Set("instance_id", items[0]) + if err != nil { + return []*schema.ResourceData{data}, err + } + err = data.Set("allow_list_id", items[1]) + if err != nil { + return []*schema.ResourceData{data}, err + } + return []*schema.ResourceData{data}, nil +} diff --git a/volcengine/vedb_mysql/vedb_mysql_allowlist_associate/service_volcengine_vedb_mysql_allowlist_associate.go b/volcengine/vedb_mysql/vedb_mysql_allowlist_associate/service_volcengine_vedb_mysql_allowlist_associate.go new file mode 100644 index 00000000..496a0688 --- /dev/null +++ b/volcengine/vedb_mysql/vedb_mysql_allowlist_associate/service_volcengine_vedb_mysql_allowlist_associate.go @@ -0,0 +1,217 @@ +package vedb_mysql_allowlist_associate + +import ( + "errors" + "fmt" + "strings" + "time" + + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + ve "github.com/volcengine/terraform-provider-volcengine/common" + "github.com/volcengine/terraform-provider-volcengine/logger" + "github.com/volcengine/terraform-provider-volcengine/volcengine/vedb_mysql/vedb_mysql_instance" +) + +type VolcengineVedbMysqlAllowlistAssociateService struct { + Client *ve.SdkClient + Dispatcher *ve.Dispatcher +} + +func NewVedbMysqlAllowlistAssociateService(c *ve.SdkClient) *VolcengineVedbMysqlAllowlistAssociateService { + return &VolcengineVedbMysqlAllowlistAssociateService{ + Client: c, + Dispatcher: &ve.Dispatcher{}, + } +} + +func (s *VolcengineVedbMysqlAllowlistAssociateService) GetClient() *ve.SdkClient { + return s.Client +} + +func (s *VolcengineVedbMysqlAllowlistAssociateService) ReadResources(m map[string]interface{}) (data []interface{}, err error) { + return nil, nil +} + +func (s *VolcengineVedbMysqlAllowlistAssociateService) ReadResource(resourceData *schema.ResourceData, id string) (data map[string]interface{}, err error) { + var ( + results interface{} + resultsMap map[string]interface{} + instanceMap map[string]interface{} + instances []interface{} + ok bool + ) + if id == "" { + id = s.ReadResourceId(resourceData.Id()) + } + ids := strings.Split(id, ":") + if len(ids) != 2 { + return data, err + } + req := map[string]interface{}{ + "AllowListId": ids[1], + } + action := "DescribeAllowListDetail" + resp, err := s.Client.UniversalClient.DoCall(getUniversalInfo(action), &req) + if err != nil { + return data, err + } + results, err = ve.ObtainSdkValue("Result", *resp) + if err != nil { + return data, err + } + if resultsMap, ok = results.(map[string]interface{}); !ok { + return resultsMap, errors.New("Value is not map ") + } + if len(resultsMap) == 0 { + return resultsMap, fmt.Errorf("veDB allowlist %s not exist ", ids[1]) + } + logger.Debug(logger.ReqFormat, action, resultsMap) + instances = resultsMap["AssociatedInstances"].([]interface{}) + logger.Debug(logger.ReqFormat, action, instances) + for _, instance := range instances { + if instanceMap, ok = instance.(map[string]interface{}); !ok { + return data, errors.New("instance is not map ") + } + if len(instanceMap) == 0 { + continue + } + if instanceMap["InstanceId"].(string) == ids[0] { + data = resultsMap + } + } + if len(data) == 0 { + return data, fmt.Errorf("veDB allowlist associate %s not exist ", id) + } + return data, err +} + +func (s *VolcengineVedbMysqlAllowlistAssociateService) RefreshResourceState(resourceData *schema.ResourceData, target []string, timeout time.Duration, id string) *resource.StateChangeConf { + return &resource.StateChangeConf{ + Pending: []string{}, + Delay: 1 * time.Second, + MinTimeout: 1 * time.Second, + Target: target, + Timeout: timeout, + Refresh: func() (result interface{}, state string, err error) { + var ( + d map[string]interface{} + status interface{} + failStates []string + ) + failStates = append(failStates, "Failed") + d, err = s.ReadResource(resourceData, id) + if err != nil { + return nil, "", err + } + status, err = ve.ObtainSdkValue("Status", d) + if err != nil { + return nil, "", err + } + for _, v := range failStates { + if v == status.(string) { + return nil, "", fmt.Errorf("vedb_mysql_allowlist_associate status error, status: %s", status.(string)) + } + } + return d, status.(string), err + }, + } +} + +func (s *VolcengineVedbMysqlAllowlistAssociateService) CreateResource(resourceData *schema.ResourceData, resource *schema.Resource) []ve.Callback { + instanceId := resourceData.Get("instance_id").(string) + allowListId := resourceData.Get("allow_list_id").(string) + callback := ve.Callback{ + Call: ve.SdkCall{ + Action: "AssociateAllowList", + ContentType: ve.ContentTypeJson, + SdkParam: &map[string]interface{}{ + "InstanceIds": []string{instanceId}, + "AllowListIds": []string{allowListId}, + }, + ExecuteCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (*map[string]interface{}, error) { + logger.Debug(logger.ReqFormat, call.Action, call.SdkParam) + return s.Client.UniversalClient.DoCall(getUniversalInfo(call.Action), call.SdkParam) + }, + AfterCall: func(d *schema.ResourceData, client *ve.SdkClient, resp *map[string]interface{}, call ve.SdkCall) error { + d.SetId(fmt.Sprint(instanceId, ":", allowListId)) + return nil + }, + LockId: func(d *schema.ResourceData) string { + return instanceId + }, + ExtraRefresh: map[ve.ResourceService]*ve.StateRefresh{ + vedb_mysql_instance.NewVedbMysqlInstanceService(s.Client): { + Target: []string{"Running"}, + Timeout: resourceData.Timeout(schema.TimeoutCreate), + ResourceId: instanceId, + }, + }, + }, + } + return []ve.Callback{callback} +} + +func (VolcengineVedbMysqlAllowlistAssociateService) WithResourceResponseHandlers(d map[string]interface{}) []ve.ResourceResponseHandler { + handler := func() (map[string]interface{}, map[string]ve.ResponseConvert, error) { + return d, nil, nil + } + return []ve.ResourceResponseHandler{handler} +} + +func (s *VolcengineVedbMysqlAllowlistAssociateService) ModifyResource(resourceData *schema.ResourceData, resource *schema.Resource) []ve.Callback { + callback := ve.Callback{} + return []ve.Callback{callback} +} + +func (s *VolcengineVedbMysqlAllowlistAssociateService) RemoveResource(resourceData *schema.ResourceData, r *schema.Resource) []ve.Callback { + instanceId := resourceData.Get("instance_id").(string) + allowListId := resourceData.Get("allow_list_id").(string) + callback := ve.Callback{ + Call: ve.SdkCall{ + Action: "DisassociateAllowList", + ContentType: ve.ContentTypeJson, + SdkParam: &map[string]interface{}{ + "InstanceIds": []string{instanceId}, + "AllowListIds": []string{allowListId}, + }, + ExecuteCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (*map[string]interface{}, error) { + logger.Debug(logger.ReqFormat, call.Action, call.SdkParam) + return s.Client.UniversalClient.DoCall(getUniversalInfo(call.Action), call.SdkParam) + }, + AfterCall: func(d *schema.ResourceData, client *ve.SdkClient, resp *map[string]interface{}, call ve.SdkCall) error { + err := ve.CheckResourceUtilRemoved(d, s.ReadResource, 10*time.Minute) + return err + }, + LockId: func(d *schema.ResourceData) string { + return instanceId + }, + ExtraRefresh: map[ve.ResourceService]*ve.StateRefresh{ + vedb_mysql_instance.NewVedbMysqlInstanceService(s.Client): { + Target: []string{"Running"}, + Timeout: resourceData.Timeout(schema.TimeoutDelete), + ResourceId: instanceId, + }, + }, + }, + } + return []ve.Callback{callback} +} + +func (s *VolcengineVedbMysqlAllowlistAssociateService) DatasourceResources(*schema.ResourceData, *schema.Resource) ve.DataSourceInfo { + return ve.DataSourceInfo{} +} + +func (s *VolcengineVedbMysqlAllowlistAssociateService) ReadResourceId(id string) string { + return id +} + +func getUniversalInfo(actionName string) ve.UniversalInfo { + return ve.UniversalInfo{ + ServiceName: "vedbm", + Version: "2022-01-01", + HttpMethod: ve.POST, + ContentType: ve.ApplicationJSON, + Action: actionName, + } +} diff --git a/volcengine/vedb_mysql/vedb_mysql_backup/data_source_volcengine_vedb_mysql_backups.go b/volcengine/vedb_mysql/vedb_mysql_backup/data_source_volcengine_vedb_mysql_backups.go new file mode 100644 index 00000000..05a3f148 --- /dev/null +++ b/volcengine/vedb_mysql/vedb_mysql_backup/data_source_volcengine_vedb_mysql_backups.go @@ -0,0 +1,155 @@ +package vedb_mysql_backup + +import ( + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + ve "github.com/volcengine/terraform-provider-volcengine/common" +) + +func DataSourceVolcengineVedbMysqlBackups() *schema.Resource { + return &schema.Resource{ + Read: dataSourceVolcengineVedbMysqlBackupsRead, + Schema: map[string]*schema.Schema{ + "instance_id": { + Type: schema.TypeString, + Required: true, + Description: "The id of the instance.", + }, + "backup_start_time": { + Type: schema.TypeString, + Optional: true, + Description: "The start time of the backup.", + }, + "backup_end_time": { + Type: schema.TypeString, + Optional: true, + Description: "The end time of the backup.", + }, + "backup_type": { + Type: schema.TypeString, + Optional: true, + Description: "The type of the backup.", + }, + "backup_status": { + Type: schema.TypeString, + Optional: true, + Description: "The status of the backup.", + }, + "backup_method": { + Type: schema.TypeString, + Optional: true, + Description: "Backup method. Currently, only physical backup is supported. The value is Physical.", + }, + "output_file": { + Type: schema.TypeString, + Optional: true, + Description: "File name where to save data source results.", + }, + "total_count": { + Type: schema.TypeInt, + Computed: true, + Description: "The total count of query.", + }, + "backups": { + Description: "The collection of query.", + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "id": { + Type: schema.TypeString, + Computed: true, + Description: "The id of the backup.", + }, + "backup_id": { + Type: schema.TypeString, + Computed: true, + Description: "The id of the backup.", + }, + "backup_start_time": { + Type: schema.TypeString, + Computed: true, + Description: "The start time of the backup.", + }, + "backup_end_time": { + Type: schema.TypeString, + Computed: true, + Description: "The end time of the backup.", + }, + "backup_type": { + Type: schema.TypeString, + Computed: true, + Description: "The type of the backup.", + }, + "backup_file_size": { + Type: schema.TypeInt, + Computed: true, + Description: "The size of the backup file.", + }, + "backup_method": { + Type: schema.TypeString, + Computed: true, + Description: "The name of the backup method.", + }, + "backup_status": { + Type: schema.TypeString, + Computed: true, + Description: "The status of the backup.", + }, + "create_type": { + Type: schema.TypeString, + Computed: true, + Description: "The type of the backup create.", + }, + "consistent_time": { + Type: schema.TypeString, + Computed: true, + Description: "The time point of consistent backup, in the format: yyyy-MM-ddTHH:mm:ssZ (UTC time).", + }, + "backup_policy": { + Type: schema.TypeList, + Computed: true, + Description: "Data backup strategy for instances.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "instance_id": { + Type: schema.TypeString, + Computed: true, + Description: "The id of the instance.", + }, + "backup_time": { + Type: schema.TypeString, + Computed: true, + Description: "The time for executing the backup task. " + + "The interval window is two hours. Format: HH:mmZ-HH:mmZ (UTC time).", + }, + "full_backup_period": { + Type: schema.TypeString, + Computed: true, + Description: "Full backup period. " + + "Multiple values are separated by English commas (,). " + + "Values:\nMonday: Monday.\nTuesday: Tuesday.\nWednesday: Wednesday.\nThursday: Thursday.\nFriday: Friday.\nSaturday: Saturday.\nSunday: Sunday.", + }, + "backup_retention_period": { + Type: schema.TypeInt, + Computed: true, + Description: "Data backup retention period, value: 7 to 30 days.", + }, + "continue_backup": { + Type: schema.TypeBool, + Computed: true, + Description: "Whether to enable continuous backup. The value is fixed as true.", + }, + }, + }, + }, + }, + }, + }, + }, + } +} + +func dataSourceVolcengineVedbMysqlBackupsRead(d *schema.ResourceData, meta interface{}) error { + service := NewVedbMysqlBackupService(meta.(*ve.SdkClient)) + return service.Dispatcher.Data(service, d, DataSourceVolcengineVedbMysqlBackups()) +} diff --git a/volcengine/vedb_mysql/vedb_mysql_backup/resource_volcengine_vedb_mysql_backup.go b/volcengine/vedb_mysql/vedb_mysql_backup/resource_volcengine_vedb_mysql_backup.go new file mode 100644 index 00000000..81cdef39 --- /dev/null +++ b/volcengine/vedb_mysql/vedb_mysql_backup/resource_volcengine_vedb_mysql_backup.go @@ -0,0 +1,156 @@ +package vedb_mysql_backup + +import ( + "fmt" + "reflect" + "sort" + "strings" + "time" + + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + ve "github.com/volcengine/terraform-provider-volcengine/common" +) + +/* + +Import +VedbMysqlBackup can be imported using the instance id and backup id, e.g. +``` +$ terraform import volcengine_vedb_mysql_backup.default instanceID:backupId +``` + +*/ + +func ResourceVolcengineVedbMysqlBackup() *schema.Resource { + resource := &schema.Resource{ + Create: resourceVolcengineVedbMysqlBackupCreate, + Read: resourceVolcengineVedbMysqlBackupRead, + Update: resourceVolcengineVedbMysqlBackupUpdate, + Delete: resourceVolcengineVedbMysqlBackupDelete, + Importer: &schema.ResourceImporter{ + State: func(data *schema.ResourceData, i interface{}) ([]*schema.ResourceData, error) { + items := strings.Split(data.Id(), ":") + if len(items) != 2 { + return []*schema.ResourceData{data}, fmt.Errorf("import id must split with ':'") + } + if err := data.Set("instance_id", items[0]); err != nil { + return []*schema.ResourceData{data}, err + } + if err := data.Set("backup_id", items[1]); err != nil { + return []*schema.ResourceData{data}, err + } + return []*schema.ResourceData{data}, nil + }, + }, + Timeouts: &schema.ResourceTimeout{ + Create: schema.DefaultTimeout(90 * time.Minute), + Update: schema.DefaultTimeout(90 * time.Minute), + Delete: schema.DefaultTimeout(90 * time.Minute), + }, + Schema: map[string]*schema.Schema{ + "instance_id": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: "The id of the instance.", + }, + "backup_id": { + Type: schema.TypeString, + Computed: true, + Description: "The id of the backup.", + }, + "backup_type": { + Optional: true, + Computed: true, + Type: schema.TypeString, + ForceNew: true, + Description: "Backup type. Currently, only full backup is supported. The value is Full.", + }, + "backup_method": { + Type: schema.TypeString, + Optional: true, + Computed: true, + ForceNew: true, + Description: "Backup method. Currently, only physical backup is supported. The value is Physical.", + }, + "backup_policy": { + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Computed: true, + Description: "Data backup strategy for instances.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "backup_time": { + Type: schema.TypeString, + Required: true, + Description: "The time for executing the backup task has an interval window of 2 hours and must be an even-hour time. " + + "Format: HH:mmZ-HH:mmZ (UTC time).", + }, + "full_backup_period": { + Type: schema.TypeString, + Required: true, + DiffSuppressFunc: func(k, old, new string, d *schema.ResourceData) bool { + if len(old) != len(new) { + return false + } + oldArr := strings.Split(old, ",") + newArr := strings.Split(new, ",") + sort.Strings(oldArr) + sort.Strings(newArr) + return reflect.DeepEqual(oldArr, newArr) + }, + Description: "Full backup period. " + + "It is recommended to select at least 2 days per week for full backup. " + + "Multiple values are separated by English commas (,). Values: Monday: Monday. Tuesday: Tuesday. Wednesday: Wednesday. Thursday: Thursday. Friday: Friday. Saturday: Saturday. Sunday: Sunday.", + }, + "backup_retention_period": { + // 文档写的string,实际返回是int + // error on reading vedb_mysql_backup "vedbm-ajg6odlhufzc:snap-67175524-a848", backup_policy.0.backup_retention_period: '' expected type 'string', got unconvertible type 'float64' + Type: schema.TypeInt, + Required: true, + Description: "Data backup retention period, value: 7 to 30 days.", + }, + }, + }, + }, + }, + } + return resource +} + +func resourceVolcengineVedbMysqlBackupCreate(d *schema.ResourceData, meta interface{}) (err error) { + service := NewVedbMysqlBackupService(meta.(*ve.SdkClient)) + err = service.Dispatcher.Create(service, d, ResourceVolcengineVedbMysqlBackup()) + if err != nil { + return fmt.Errorf("error on creating vedb_mysql_backup %q, %s", d.Id(), err) + } + return resourceVolcengineVedbMysqlBackupRead(d, meta) +} + +func resourceVolcengineVedbMysqlBackupRead(d *schema.ResourceData, meta interface{}) (err error) { + service := NewVedbMysqlBackupService(meta.(*ve.SdkClient)) + err = service.Dispatcher.Read(service, d, ResourceVolcengineVedbMysqlBackup()) + if err != nil { + return fmt.Errorf("error on reading vedb_mysql_backup %q, %s", d.Id(), err) + } + return err +} + +func resourceVolcengineVedbMysqlBackupUpdate(d *schema.ResourceData, meta interface{}) (err error) { + service := NewVedbMysqlBackupService(meta.(*ve.SdkClient)) + err = service.Dispatcher.Update(service, d, ResourceVolcengineVedbMysqlBackup()) + if err != nil { + return fmt.Errorf("error on updating vedb_mysql_backup %q, %s", d.Id(), err) + } + return resourceVolcengineVedbMysqlBackupRead(d, meta) +} + +func resourceVolcengineVedbMysqlBackupDelete(d *schema.ResourceData, meta interface{}) (err error) { + service := NewVedbMysqlBackupService(meta.(*ve.SdkClient)) + err = service.Dispatcher.Delete(service, d, ResourceVolcengineVedbMysqlBackup()) + if err != nil { + return fmt.Errorf("error on deleting vedb_mysql_backup %q, %s", d.Id(), err) + } + return err +} diff --git a/volcengine/vedb_mysql/vedb_mysql_backup/service_volcengine_vedb_mysql_backup.go b/volcengine/vedb_mysql/vedb_mysql_backup/service_volcengine_vedb_mysql_backup.go new file mode 100644 index 00000000..945c6061 --- /dev/null +++ b/volcengine/vedb_mysql/vedb_mysql_backup/service_volcengine_vedb_mysql_backup.go @@ -0,0 +1,343 @@ +package vedb_mysql_backup + +import ( + "encoding/json" + "errors" + "fmt" + "strings" + "time" + + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + ve "github.com/volcengine/terraform-provider-volcengine/common" + "github.com/volcengine/terraform-provider-volcengine/logger" + "github.com/volcengine/terraform-provider-volcengine/volcengine/vedb_mysql/vedb_mysql_instance" +) + +type VolcengineVedbMysqlBackupService struct { + Client *ve.SdkClient + Dispatcher *ve.Dispatcher +} + +func NewVedbMysqlBackupService(c *ve.SdkClient) *VolcengineVedbMysqlBackupService { + return &VolcengineVedbMysqlBackupService{ + Client: c, + Dispatcher: &ve.Dispatcher{}, + } +} + +func (s *VolcengineVedbMysqlBackupService) GetClient() *ve.SdkClient { + return s.Client +} + +func (s *VolcengineVedbMysqlBackupService) ReadResources(m map[string]interface{}) (data []interface{}, err error) { + var ( + resp *map[string]interface{} + results interface{} + ok bool + ) + return ve.WithPageNumberQuery(m, "PageSize", "PageNumber", 100, 1, func(condition map[string]interface{}) ([]interface{}, error) { + action := "DescribeBackups" + + bytes, _ := json.Marshal(condition) + logger.Debug(logger.ReqFormat, action, string(bytes)) + if condition == nil { + resp, err = s.Client.UniversalClient.DoCall(getUniversalInfo(action), nil) + if err != nil { + return data, err + } + } else { + resp, err = s.Client.UniversalClient.DoCall(getUniversalInfo(action), &condition) + if err != nil { + return data, err + } + } + respBytes, _ := json.Marshal(resp) + logger.Debug(logger.RespFormat, action, condition, string(respBytes)) + results, err = ve.ObtainSdkValue("Result.BackupsInfo", *resp) + if err != nil { + return data, err + } + if results == nil { + results = []interface{}{} + } + if data, ok = results.([]interface{}); !ok { + return data, errors.New("Result.BackupsInfo is not Slice") + } + for _, v := range data { + backup := v.(map[string]interface{}) + instanceId := condition["InstanceId"] + action = "DescribeBackupPolicy" + req := map[string]interface{}{ + "InstanceId": instanceId, + } + resp, err = s.Client.UniversalClient.DoCall(getUniversalInfo(action), &req) + if err != nil { + logger.Info("DescribeBackupPolicy error : ", err) + continue + } + respBytes, _ = json.Marshal(resp) + logger.Debug(logger.RespFormat, action, req, string(respBytes)) + + result, err := ve.ObtainSdkValue("Result", *resp) + if err != nil { + logger.Info("ObtainSdkValue Result error:", err) + continue + } + backup["BackupPolicy"] = result + } + return data, err + }) +} + +func (s *VolcengineVedbMysqlBackupService) ReadResource(resourceData *schema.ResourceData, id string) (data map[string]interface{}, err error) { + var ( + results []interface{} + tmpData map[string]interface{} + ok bool + ) + if id == "" { + id = s.ReadResourceId(resourceData.Id()) + } + ids := strings.Split(id, ":") + req := map[string]interface{}{ + "InstanceId": ids[0], + } + results, err = s.ReadResources(req) + if err != nil { + return data, err + } + for _, v := range results { + if tmpData, ok = v.(map[string]interface{}); !ok { + return data, errors.New("Value is not map ") + } else if tmpData["BackupId"].(string) == ids[1] { + data = tmpData + } + } + if len(data) == 0 { + return data, fmt.Errorf("vedb_mysql_backup %s not exist ", id) + } + return data, err +} + +func (s *VolcengineVedbMysqlBackupService) RefreshResourceState(resourceData *schema.ResourceData, target []string, timeout time.Duration, id string) *resource.StateChangeConf { + return &resource.StateChangeConf{ + Pending: []string{}, + Delay: 1 * time.Second, + MinTimeout: 1 * time.Second, + Target: target, + Timeout: timeout, + Refresh: func() (result interface{}, state string, err error) { + var ( + d map[string]interface{} + status interface{} + failStates []string + ) + failStates = append(failStates, "Failed") + d, err = s.ReadResource(resourceData, id) + if err != nil { + return nil, "", err + } + status, err = ve.ObtainSdkValue("BackupStatus", d) + if err != nil { + return nil, "", err + } + for _, v := range failStates { + if v == status.(string) { + return nil, "", fmt.Errorf("vedb_mysql_backup status error, status: %s", status.(string)) + } + } + return d, status.(string), err + }, + } +} + +func (s *VolcengineVedbMysqlBackupService) CreateResource(resourceData *schema.ResourceData, resource *schema.Resource) []ve.Callback { + var callbacks []ve.Callback + callback := ve.Callback{ + Call: ve.SdkCall{ + Action: "CreateBackup", + ConvertMode: ve.RequestConvertAll, + ContentType: ve.ContentTypeJson, + Convert: map[string]ve.RequestConvert{ + "backup_policy": { + Ignore: true, + }, + }, + ExecuteCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (*map[string]interface{}, error) { + logger.Debug(logger.RespFormat, call.Action, call.SdkParam) + resp, err := s.Client.UniversalClient.DoCall(getUniversalInfo(call.Action), call.SdkParam) + logger.Debug(logger.RespFormat, call.Action, resp, err) + return resp, err + }, + AfterCall: func(d *schema.ResourceData, client *ve.SdkClient, resp *map[string]interface{}, call ve.SdkCall) error { + instanceId := (*call.SdkParam)["InstanceId"] + backupId, _ := ve.ObtainSdkValue("Result.BackupId", *resp) + d.SetId(fmt.Sprintf("%s:%s", instanceId, backupId)) + return nil + }, + Refresh: &ve.StateRefresh{ + Target: []string{"Success"}, + Timeout: resourceData.Timeout(schema.TimeoutCreate), + }, + LockId: func(d *schema.ResourceData) string { + return d.Get("instance_id").(string) + }, + ExtraRefresh: map[ve.ResourceService]*ve.StateRefresh{ + vedb_mysql_instance.NewVedbMysqlInstanceService(s.Client): { + Target: []string{"Running"}, + Timeout: resourceData.Timeout(schema.TimeoutCreate), + ResourceId: resourceData.Get("instance_id").(string), + }, + }, + }, + } + callbacks = append(callbacks, callback) + policy, ok := resourceData.GetOk("backup_policy") + if ok { + policyCallback := ve.Callback{ + Call: ve.SdkCall{ + Action: "ModifyBackupPolicy", + ConvertMode: ve.RequestConvertIgnore, + ContentType: ve.ContentTypeJson, + BeforeCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (bool, error) { + policyList, ok := policy.([]interface{}) + if !ok { + return false, fmt.Errorf("policy is not a list") + } + p := policyList[0].(map[string]interface{}) + (*call.SdkParam)["InstanceId"] = d.Get("instance_id").(string) + (*call.SdkParam)["BackupTime"] = p["backup_time"] + (*call.SdkParam)["FullBackupPeriod"] = p["full_backup_period"] + (*call.SdkParam)["BackupRetentionPeriod"] = p["backup_retention_period"] + return true, nil + }, + ExecuteCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (*map[string]interface{}, error) { + logger.Debug(logger.RespFormat, call.Action, call.SdkParam) + resp, err := s.Client.UniversalClient.DoCall(getUniversalInfo(call.Action), call.SdkParam) + logger.Debug(logger.RespFormat, call.Action, resp, err) + return resp, err + }, + Refresh: &ve.StateRefresh{ + Target: []string{"Success"}, + Timeout: resourceData.Timeout(schema.TimeoutCreate), + }, + LockId: func(d *schema.ResourceData) string { + return d.Get("instance_id").(string) + }, + ExtraRefresh: map[ve.ResourceService]*ve.StateRefresh{ + vedb_mysql_instance.NewVedbMysqlInstanceService(s.Client): { + Target: []string{"Running"}, + Timeout: resourceData.Timeout(schema.TimeoutCreate), + ResourceId: resourceData.Get("instance_id").(string), + }, + }, + }, + } + callbacks = append(callbacks, policyCallback) + } + return callbacks +} + +func (VolcengineVedbMysqlBackupService) WithResourceResponseHandlers(d map[string]interface{}) []ve.ResourceResponseHandler { + handler := func() (map[string]interface{}, map[string]ve.ResponseConvert, error) { + return d, nil, nil + } + return []ve.ResourceResponseHandler{handler} +} + +func (s *VolcengineVedbMysqlBackupService) ModifyResource(resourceData *schema.ResourceData, resource *schema.Resource) []ve.Callback { + callback := ve.Callback{ + Call: ve.SdkCall{ + Action: "ModifyBackupPolicy", + ConvertMode: ve.RequestConvertIgnore, + BeforeCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (bool, error) { + policy, ok := resourceData.GetOk("backup_policy") + if !ok { + return false, nil + } + policyList, ok := policy.([]interface{}) + if !ok { + return false, fmt.Errorf("policy is not a list") + } + p := policyList[0].(map[string]interface{}) + (*call.SdkParam)["InstanceId"] = d.Get("instance_id").(string) + (*call.SdkParam)["BackupTime"] = p["backup_time"] + (*call.SdkParam)["FullBackupPeriod"] = p["full_backup_period"] + (*call.SdkParam)["BackupRetentionPeriod"] = p["backup_retention_period"] + return true, nil + }, + ExecuteCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (*map[string]interface{}, error) { + logger.Debug(logger.ReqFormat, call.Action, call.SdkParam) + resp, err := s.Client.UniversalClient.DoCall(getUniversalInfo(call.Action), call.SdkParam) + logger.Debug(logger.RespFormat, call.Action, resp, err) + return resp, err + }, + Refresh: &ve.StateRefresh{ + Target: []string{"Success"}, + Timeout: resourceData.Timeout(schema.TimeoutCreate), + }, + LockId: func(d *schema.ResourceData) string { + return d.Get("instance_id").(string) + }, + ExtraRefresh: map[ve.ResourceService]*ve.StateRefresh{ + vedb_mysql_instance.NewVedbMysqlInstanceService(s.Client): { + Target: []string{"Running"}, + Timeout: resourceData.Timeout(schema.TimeoutCreate), + ResourceId: resourceData.Get("instance_id").(string), + }, + }, + }, + } + return []ve.Callback{callback} +} + +func (s *VolcengineVedbMysqlBackupService) RemoveResource(resourceData *schema.ResourceData, r *schema.Resource) []ve.Callback { + ids := strings.Split(resourceData.Id(), ":") + callback := ve.Callback{ + Call: ve.SdkCall{ + Action: "DeleteBackup", + ConvertMode: ve.RequestConvertIgnore, + ContentType: ve.ContentTypeJson, + SdkParam: &map[string]interface{}{ + "InstanceId": ids[0], + "BackupId": ids[1], + }, + ExecuteCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (*map[string]interface{}, error) { + logger.Debug(logger.RespFormat, call.Action, call.SdkParam) + return s.Client.UniversalClient.DoCall(getUniversalInfo(call.Action), call.SdkParam) + }, + AfterCall: func(d *schema.ResourceData, client *ve.SdkClient, resp *map[string]interface{}, call ve.SdkCall) error { + return ve.CheckResourceUtilRemoved(d, s.ReadResource, 5*time.Minute) + }, + }, + } + return []ve.Callback{callback} +} + +func (s *VolcengineVedbMysqlBackupService) DatasourceResources(*schema.ResourceData, *schema.Resource) ve.DataSourceInfo { + return ve.DataSourceInfo{ + IdField: "BackupId", + CollectField: "backups", + ResponseConverts: map[string]ve.ResponseConvert{ + "BackupId": { + TargetField: "id", + KeepDefault: true, + }, + }, + } +} + +func (s *VolcengineVedbMysqlBackupService) ReadResourceId(id string) string { + return id +} + +func getUniversalInfo(actionName string) ve.UniversalInfo { + return ve.UniversalInfo{ + ServiceName: "vedbm", + Version: "2022-01-01", + HttpMethod: ve.POST, + ContentType: ve.ApplicationJSON, + Action: actionName, + } +} diff --git a/volcengine/vedb_mysql/vedb_mysql_database/data_source_volcengine_vedb_mysql_databases.go b/volcengine/vedb_mysql/vedb_mysql_database/data_source_volcengine_vedb_mysql_databases.go new file mode 100644 index 00000000..8b3347b4 --- /dev/null +++ b/volcengine/vedb_mysql/vedb_mysql_database/data_source_volcengine_vedb_mysql_databases.go @@ -0,0 +1,106 @@ +package vedb_mysql_database + +import ( + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/helper/validation" + ve "github.com/volcengine/terraform-provider-volcengine/common" +) + +func DataSourceVolcengineVedbMysqlDatabases() *schema.Resource { + return &schema.Resource{ + Read: dataSourceVolcengineVedbMysqlDatabasesRead, + Schema: map[string]*schema.Schema{ + "instance_id": { + Type: schema.TypeString, + Required: true, + Description: "The instance id.", + }, + "db_name": { + Type: schema.TypeString, + Optional: true, + Description: "Database name.", + }, + "name_regex": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.StringIsValidRegExp, + Description: "A Name Regex of Resource.", + }, + "output_file": { + Type: schema.TypeString, + Optional: true, + Description: "File name where to save data source results.", + }, + "total_count": { + Type: schema.TypeInt, + Computed: true, + Description: "The total count of query.", + }, + "databases": { + Description: "The collection of query.", + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "db_name": { + Type: schema.TypeString, + Computed: true, + Description: "The name of the database. Naming rules:\n " + + "Unique name. Start with a lowercase letter and end with a letter or number. " + + "The length is within 2 to 64 characters.\n " + + "Consist of lowercase letters, numbers, underscores (_), or hyphens (-).\n " + + "The name cannot contain certain reserved words.", + }, + "character_set_name": { + Type: schema.TypeString, + Computed: true, + Description: "Database character set: utf8mb4 (default), utf8, latin1, ascii.", + }, + "databases_privileges": { + Type: schema.TypeSet, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "account_name": { + Type: schema.TypeString, + Computed: true, + Description: "Account name that requires authorization.", + }, + "account_privilege": { + Type: schema.TypeString, + Computed: true, + Description: "Authorization database privilege types: " + + "\nReadWrite: Read and write privilege.\n " + + "ReadOnly: Read-only privilege.\n " + + "DDLOnly: Only DDL privilege.\n " + + "DMLOnly: Only DML privilege.\n " + + "Custom: Custom privilege.", + }, + "account_privilege_detail": { + Type: schema.TypeString, + Computed: true, + Description: "The specific SQL operation permissions contained in the permission type are separated by English commas (,) between multiple strings.\n " + + "When used as a request parameter in the CreateDatabase interface, " + + "when the AccountPrivilege value is Custom, this parameter is required. " + + "Value range (multiple selections allowed): SELECT, INSERT, UPDATE, DELETE," + + " CREATE, DROP, REFERENCES, INDEX, ALTER, CREATE TEMPORARY TABLES, LOCK TABLES, " + + "EXECUTE, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, EVENT, TRIGGER. " + + "When used as a return parameter in the DescribeDatabases interface, " + + "regardless of the value of AccountPrivilege, the details of the SQL operation permissions contained in this permission type are returned. " + + "For the specific SQL operation permissions contained in each permission type, " + + "please refer to the account permission list.", + }, + }, + }, + }, + }, + }, + }, + }, + } +} + +func dataSourceVolcengineVedbMysqlDatabasesRead(d *schema.ResourceData, meta interface{}) error { + service := NewVedbMysqlDatabaseService(meta.(*ve.SdkClient)) + return service.Dispatcher.Data(service, d, DataSourceVolcengineVedbMysqlDatabases()) +} diff --git a/volcengine/vedb_mysql/vedb_mysql_database/resource_volcengine_vedb_mysql_database.go b/volcengine/vedb_mysql/vedb_mysql_database/resource_volcengine_vedb_mysql_database.go new file mode 100644 index 00000000..86338639 --- /dev/null +++ b/volcengine/vedb_mysql/vedb_mysql_database/resource_volcengine_vedb_mysql_database.go @@ -0,0 +1,103 @@ +package vedb_mysql_database + +import ( + "fmt" + "strings" + "time" + + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + ve "github.com/volcengine/terraform-provider-volcengine/common" +) + +/* + +Import +VedbMysqlDatabase can be imported using the instance id and database name, e.g. +``` +$ terraform import volcengine_vedb_mysql_database.default vedbm-r3xq0zdl****:testdb + +``` + +*/ + +func ResourceVolcengineVedbMysqlDatabase() *schema.Resource { + resource := &schema.Resource{ + Create: resourceVolcengineVedbMysqlDatabaseCreate, + Read: resourceVolcengineVedbMysqlDatabaseRead, + Delete: resourceVolcengineVedbMysqlDatabaseDelete, + Importer: &schema.ResourceImporter{ + State: vedbMysqlDatabaseImporter, + }, + Timeouts: &schema.ResourceTimeout{ + Create: schema.DefaultTimeout(30 * time.Minute), + Delete: schema.DefaultTimeout(30 * time.Minute), + }, + Schema: map[string]*schema.Schema{ + "instance_id": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: "The id of the instance.", + }, + "db_name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: "The name of the database. Naming rules:\n " + + "Unique name. Start with a lowercase letter and end with a letter or number. " + + "The length is within 2 to 64 characters.\n " + + "Consist of lowercase letters, numbers, underscores (_), or hyphens (-).\n " + + "The name cannot contain certain reserved words.", + }, + "character_set_name": { + Type: schema.TypeString, + Optional: true, + Computed: true, + ForceNew: true, + Description: "Database character set: utf8mb4 (default), utf8, latin1, ascii.", + }, + }, + } + return resource +} + +func resourceVolcengineVedbMysqlDatabaseCreate(d *schema.ResourceData, meta interface{}) (err error) { + service := NewVedbMysqlDatabaseService(meta.(*ve.SdkClient)) + err = service.Dispatcher.Create(service, d, ResourceVolcengineVedbMysqlDatabase()) + if err != nil { + return fmt.Errorf("error on creating vedb_mysql_database %q, %s", d.Id(), err) + } + return resourceVolcengineVedbMysqlDatabaseRead(d, meta) +} + +func resourceVolcengineVedbMysqlDatabaseRead(d *schema.ResourceData, meta interface{}) (err error) { + service := NewVedbMysqlDatabaseService(meta.(*ve.SdkClient)) + err = service.Dispatcher.Read(service, d, ResourceVolcengineVedbMysqlDatabase()) + if err != nil { + return fmt.Errorf("error on reading vedb_mysql_database %q, %s", d.Id(), err) + } + return err +} + +func resourceVolcengineVedbMysqlDatabaseDelete(d *schema.ResourceData, meta interface{}) (err error) { + service := NewVedbMysqlDatabaseService(meta.(*ve.SdkClient)) + err = service.Dispatcher.Delete(service, d, ResourceVolcengineVedbMysqlDatabase()) + if err != nil { + return fmt.Errorf("error on deleting vedb_mysql_database %q, %s", d.Id(), err) + } + return err +} + +var vedbMysqlDatabaseImporter = func(data *schema.ResourceData, i interface{}) ([]*schema.ResourceData, error) { + items := strings.Split(data.Id(), ":") + if len(items) != 2 { + return []*schema.ResourceData{data}, fmt.Errorf("import id must split with ':'") + } + if err := data.Set("instance_id", items[0]); err != nil { + return []*schema.ResourceData{data}, err + } + if err := data.Set("db_name", items[1]); err != nil { + return []*schema.ResourceData{data}, err + } + return []*schema.ResourceData{data}, nil +} diff --git a/volcengine/vedb_mysql/vedb_mysql_database/service_volcengine_vedb_mysql_database.go b/volcengine/vedb_mysql/vedb_mysql_database/service_volcengine_vedb_mysql_database.go new file mode 100644 index 00000000..1c65f97b --- /dev/null +++ b/volcengine/vedb_mysql/vedb_mysql_database/service_volcengine_vedb_mysql_database.go @@ -0,0 +1,266 @@ +package vedb_mysql_database + +import ( + "encoding/json" + "errors" + "fmt" + "strings" + "time" + + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + ve "github.com/volcengine/terraform-provider-volcengine/common" + "github.com/volcengine/terraform-provider-volcengine/logger" + "github.com/volcengine/terraform-provider-volcengine/volcengine/vedb_mysql/vedb_mysql_instance" +) + +type VolcengineVedbMysqlDatabaseService struct { + Client *ve.SdkClient + Dispatcher *ve.Dispatcher +} + +func NewVedbMysqlDatabaseService(c *ve.SdkClient) *VolcengineVedbMysqlDatabaseService { + return &VolcengineVedbMysqlDatabaseService{ + Client: c, + Dispatcher: &ve.Dispatcher{}, + } +} + +func (s *VolcengineVedbMysqlDatabaseService) GetClient() *ve.SdkClient { + return s.Client +} + +func (s *VolcengineVedbMysqlDatabaseService) ReadResources(m map[string]interface{}) (data []interface{}, err error) { + var ( + resp *map[string]interface{} + results interface{} + ok bool + ) + return ve.WithPageNumberQuery(m, "PageSize", "PageNumber", 100, 1, func(condition map[string]interface{}) ([]interface{}, error) { + action := "DescribeDatabases" + + bytes, _ := json.Marshal(condition) + logger.Debug(logger.ReqFormat, action, string(bytes)) + if condition == nil { + resp, err = s.Client.UniversalClient.DoCall(getUniversalInfo(action), nil) + if err != nil { + return data, err + } + } else { + resp, err = s.Client.UniversalClient.DoCall(getUniversalInfo(action), &condition) + if err != nil { + return data, err + } + } + respBytes, _ := json.Marshal(resp) + logger.Debug(logger.RespFormat, action, condition, string(respBytes)) + + results, err = ve.ObtainSdkValue("Result.Databases", *resp) + if err != nil { + return data, err + } + if results == nil { + results = []interface{}{} + } + if data, ok = results.([]interface{}); !ok { + return data, errors.New("Result.Databases is not Slice") + } + return data, err + }) +} + +func (s *VolcengineVedbMysqlDatabaseService) ReadResource(resourceData *schema.ResourceData, id string) (data map[string]interface{}, err error) { + var ( + results []interface{} + ok bool + ) + if id == "" { + id = s.ReadResourceId(resourceData.Id()) + } + + ids := strings.Split(id, ":") + if len(ids) != 2 { + return nil, errors.New("ids length is not correct") + } + + req := map[string]interface{}{ + "InstanceId": ids[0], + "DBName": ids[1], + } + results, err = s.ReadResources(req) + if err != nil { + return data, err + } + for _, v := range results { + if data, ok = v.(map[string]interface{}); !ok { + return data, errors.New("Value is not map ") + } + } + if len(data) == 0 { + return data, fmt.Errorf("vedb_mysql_database %s not exist ", id) + } + return data, err +} + +func (s *VolcengineVedbMysqlDatabaseService) RefreshResourceState(resourceData *schema.ResourceData, target []string, timeout time.Duration, id string) *resource.StateChangeConf { + return &resource.StateChangeConf{ + Pending: []string{}, + Delay: 1 * time.Second, + MinTimeout: 1 * time.Second, + Target: target, + Timeout: timeout, + Refresh: func() (result interface{}, state string, err error) { + var ( + d map[string]interface{} + status interface{} + failStates []string + ) + failStates = append(failStates, "Failed") + d, err = s.ReadResource(resourceData, id) + if err != nil { + return nil, "", err + } + status, err = ve.ObtainSdkValue("Status", d) + if err != nil { + return nil, "", err + } + for _, v := range failStates { + if v == status.(string) { + return nil, "", fmt.Errorf("vedb_mysql_database status error, status: %s", status.(string)) + } + } + return d, status.(string), err + }, + } +} + +func (s *VolcengineVedbMysqlDatabaseService) CreateResource(resourceData *schema.ResourceData, resource *schema.Resource) []ve.Callback { + callback := ve.Callback{ + Call: ve.SdkCall{ + Action: "CreateDatabase", + ConvertMode: ve.RequestConvertAll, + ContentType: ve.ContentTypeJson, + Convert: map[string]ve.RequestConvert{ + "db_name": { + TargetField: "DBName", + }, + }, + ExecuteCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (*map[string]interface{}, error) { + logger.Debug(logger.RespFormat, call.Action, call.SdkParam) + resp, err := s.Client.UniversalClient.DoCall(getUniversalInfo(call.Action), call.SdkParam) + logger.Debug(logger.RespFormat, call.Action, resp, err) + return resp, err + }, + AfterCall: func(d *schema.ResourceData, client *ve.SdkClient, resp *map[string]interface{}, call ve.SdkCall) error { + d.SetId(fmt.Sprint((*call.SdkParam)["InstanceId"], ":", (*call.SdkParam)["DBName"])) + return nil + }, + LockId: func(d *schema.ResourceData) string { + return d.Get("instance_id").(string) + }, + ExtraRefresh: map[ve.ResourceService]*ve.StateRefresh{ + vedb_mysql_instance.NewVedbMysqlInstanceService(s.Client): { + Target: []string{"Running"}, + Timeout: resourceData.Timeout(schema.TimeoutDelete), + ResourceId: resourceData.Get("instance_id").(string), + }, + }, + }, + } + return []ve.Callback{callback} +} + +func (VolcengineVedbMysqlDatabaseService) WithResourceResponseHandlers(d map[string]interface{}) []ve.ResourceResponseHandler { + handler := func() (map[string]interface{}, map[string]ve.ResponseConvert, error) { + return d, map[string]ve.ResponseConvert{ + "DBName": { + TargetField: "db_name", + }, + }, nil + } + return []ve.ResourceResponseHandler{handler} +} + +func (s *VolcengineVedbMysqlDatabaseService) ModifyResource(resourceData *schema.ResourceData, resource *schema.Resource) []ve.Callback { + callback := ve.Callback{} + return []ve.Callback{callback} +} + +func (s *VolcengineVedbMysqlDatabaseService) RemoveResource(resourceData *schema.ResourceData, r *schema.Resource) []ve.Callback { + callback := ve.Callback{ + Call: ve.SdkCall{ + Action: "DeleteDatabase", + ConvertMode: ve.RequestConvertIgnore, + ContentType: ve.ContentTypeJson, + BeforeCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (bool, error) { + ids := strings.Split(d.Id(), ":") + (*call.SdkParam)["InstanceId"] = ids[0] + (*call.SdkParam)["DBName"] = ids[1] + return true, nil + }, + ExecuteCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (*map[string]interface{}, error) { + logger.Debug(logger.RespFormat, call.Action, call.SdkParam) + return s.Client.UniversalClient.DoCall(getUniversalInfo(call.Action), call.SdkParam) + }, + AfterCall: func(d *schema.ResourceData, client *ve.SdkClient, resp *map[string]interface{}, call ve.SdkCall) error { + return ve.CheckResourceUtilRemoved(d, s.ReadResource, 5*time.Minute) + }, + LockId: func(d *schema.ResourceData) string { + return d.Get("instance_id").(string) + }, + ExtraRefresh: map[ve.ResourceService]*ve.StateRefresh{ + vedb_mysql_instance.NewVedbMysqlInstanceService(s.Client): { + Target: []string{"Running"}, + Timeout: resourceData.Timeout(schema.TimeoutDelete), + ResourceId: resourceData.Get("instance_id").(string), + }, + }, + CallError: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall, baseErr error) error { + //出现错误后重试 + return resource.Retry(15*time.Minute, func() *resource.RetryError { + _, callErr := s.ReadResource(d, "") + if callErr != nil { + if ve.ResourceNotFoundError(callErr) { + return nil + } else { + return resource.NonRetryableError(fmt.Errorf("error on reading vedb mysql database on delete %q, %w", d.Id(), callErr)) + } + } + _, callErr = call.ExecuteCall(d, client, call) + if callErr == nil { + return nil + } + return resource.RetryableError(callErr) + }) + }, + }, + } + return []ve.Callback{callback} +} + +func (s *VolcengineVedbMysqlDatabaseService) DatasourceResources(*schema.ResourceData, *schema.Resource) ve.DataSourceInfo { + return ve.DataSourceInfo{ + RequestConverts: map[string]ve.RequestConvert{}, + NameField: "DBName", + CollectField: "databases", + ResponseConverts: map[string]ve.ResponseConvert{ + "DBName": { + TargetField: "db_name", + }, + }, + } +} + +func (s *VolcengineVedbMysqlDatabaseService) ReadResourceId(id string) string { + return id +} + +func getUniversalInfo(actionName string) ve.UniversalInfo { + return ve.UniversalInfo{ + ServiceName: "vedbm", + Version: "2022-01-01", + HttpMethod: ve.POST, + ContentType: ve.ApplicationJSON, + Action: actionName, + } +} diff --git a/volcengine/vedb_mysql/vedb_mysql_endpoint/data_source_volcengine_vedb_mysql_endpoints.go b/volcengine/vedb_mysql/vedb_mysql_endpoint/data_source_volcengine_vedb_mysql_endpoints.go new file mode 100644 index 00000000..dffe1839 --- /dev/null +++ b/volcengine/vedb_mysql/vedb_mysql_endpoint/data_source_volcengine_vedb_mysql_endpoints.go @@ -0,0 +1,202 @@ +package vedb_mysql_endpoint + +import ( + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/helper/validation" + ve "github.com/volcengine/terraform-provider-volcengine/common" +) + +func DataSourceVolcengineVedbMysqlEndpoints() *schema.Resource { + return &schema.Resource{ + Read: dataSourceVolcengineVedbMysqlEndpointsRead, + Schema: map[string]*schema.Schema{ + "instance_id": { + Type: schema.TypeString, + Required: true, + Description: "The id of the instance.", + }, + "endpoint_id": { + Type: schema.TypeString, + Optional: true, + Description: "The id of the endpoint.", + }, + "name_regex": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.StringIsValidRegExp, + Description: "A Name Regex of Resource.", + }, + "output_file": { + Type: schema.TypeString, + Optional: true, + Description: "File name where to save data source results.", + }, + "total_count": { + Type: schema.TypeInt, + Computed: true, + Description: "The total count of query.", + }, + "endpoints": { + Description: "The collection of query.", + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "id": { + Type: schema.TypeString, + Computed: true, + Description: "The id of the endpoint.", + }, + "endpoint_id": { + Type: schema.TypeString, + Computed: true, + Description: "The id of the endpoint.", + }, + "endpoint_type": { + Type: schema.TypeString, + Computed: true, + Description: "Connect terminal type. The value is fixed as Custom, indicating a custom terminal.", + }, + "read_write_mode": { + Type: schema.TypeString, + Computed: true, + Description: "Endpoint read-write mode. Values:\n ReadWrite: Read and write terminal.\n ReadOnly: Read-only terminal (default).", + }, + "endpoint_name": { + Type: schema.TypeString, + Computed: true, + Description: "Connect the endpoint name. The setting rules are as follows:\n " + + "It cannot start with a number or a hyphen (-).\n " + + "It can only contain Chinese characters, letters, numbers, underscores (_), and hyphens (-).\n " + + "The length is 1 to 64 characters.", + }, + "description": { + Type: schema.TypeString, + Computed: true, + Description: "Description information for connecting endpoint. The length cannot exceed 200 characters.", + }, + "node_ids": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + Description: "Connect the node IDs associated with the endpoint." + + "The filling rules are as follows:\n" + + "When the value of ReadWriteMode is ReadWrite, at least two nodes must be passed in, and the master node must be passed in.\n" + + "When the value of ReadWriteMode is ReadOnly, one or more read-only nodes can be passed in.", + }, + "auto_add_new_nodes": { + Type: schema.TypeBool, + Computed: true, + Description: "Set whether newly created read-only nodes will automatically join this connection endpoint." + + " Values:\ntrue: Automatically join.\nfalse: Do not automatically join (default).", + }, + "master_accept_read_requests": { + Type: schema.TypeBool, + Computed: true, + Description: "The master node accepts read requests. " + + "Value range:\ntrue: (default) After enabling the master node to accept read functions, " + + "non-transactional read requests will be sent to the master node or read-only nodes in a load-balanced mode according to the number of active requests." + + "\nfalse: After disabling the master node from accepting read requests, at this time," + + " the master node only accepts transactional read requests, " + + "and non-transactional read requests will not be sent to the master node.\n" + + "Description\nOnly when the value of ReadWriteMode is ReadWrite, " + + "enabling the master node to accept reads is supported.", + }, + "distributed_transaction": { + Type: schema.TypeBool, + Computed: true, + Description: "Set whether to enable transaction splitting. " + + "For detailed introduction to transaction splitting, please refer to transaction splitting." + + " Value range:\ntrue: Enabled (default).\nfalse: Disabled.\n" + + "Description\nOnly when the value of ReadWriteMode is ReadWrite, is enabling transaction splitting supported.", + }, + "consist_level": { + Type: schema.TypeString, + Computed: true, + Description: "Consistency level. " + + "For detailed introduction of consistency level, " + + "please refer to consistency level. " + + "Value range:\nEventual: eventual consistency.\n" + + "Session: session consistency.\nGlobal: global consistency.\n" + + "Description\nWhen the value of ReadWriteMode is ReadWrite, " + + "the selectable consistency levels are Eventual, Session (default), and Global." + + "\nWhen the value of ReadWriteMode is ReadOnly, the consistency level is Eventual by default and cannot be changed.", + }, + "consist_timeout": { + Type: schema.TypeInt, + Computed: true, + Description: "When there is a large delay, " + + "the timeout period for read-only nodes to synchronize the latest data, in us. " + + "The value range is from 1us to 100000000us, and the default value is 10000us.\n" + + "Explanation\n This parameter takes effect only when the value of ConsistLevel is Global or Session.", + }, + "consist_timeout_action": { + Type: schema.TypeString, + Computed: true, + Description: "Timeout policy after data synchronization timeout of read-only nodes supports the following two policies:" + + "\nReturnError: Return SQL error (wait replication complete timeout, please retry)." + + "\nReadMaster: Send a request to the master node (default).\n" + + "Description\n This parameter takes effect only when the value of ConsistLevel is Global or Session.", + }, + "addresses": { + Type: schema.TypeList, + Computed: true, + Description: "The address information.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "dns_visibility": { + Type: schema.TypeBool, + Computed: true, + Description: "Parsing method. Currently, the return value can only be false (Volcengine private network parsing).", + }, + "domain": { + Type: schema.TypeString, + Computed: true, + Description: "Instance intranet access domain name.", + }, + "ip_address": { + Type: schema.TypeString, + Computed: true, + Description: "IP address.", + }, + "network_type": { + Type: schema.TypeString, + Computed: true, + Description: "Network type:\nPrivate: Private network VPC.\nPublic: Public network access.", + }, + "port": { + Type: schema.TypeString, + Computed: true, + Description: "Instance intranet access port.", + }, + "subnet_id": { + Type: schema.TypeString, + Computed: true, + Description: "Subnet ID. " + + "The subnet must belong to the selected availability zone.\n" + + "Description\n " + + "A subnet is an IP address block within a private network. " + + "All cloud resources in a private network must be deployed within a subnet. " + + "The subnet assigns private IP addresses to cloud resources.", + }, + "eip_id": { + Type: schema.TypeString, + Computed: true, + Description: "The EIP id.", + }, + }, + }, + }, + }, + }, + }, + }, + } +} + +func dataSourceVolcengineVedbMysqlEndpointsRead(d *schema.ResourceData, meta interface{}) error { + service := NewVedbMysqlEndpointService(meta.(*ve.SdkClient)) + return service.Dispatcher.Data(service, d, DataSourceVolcengineVedbMysqlEndpoints()) +} diff --git a/volcengine/vedb_mysql/vedb_mysql_endpoint/resource_volcengine_vedb_mysql_endpoint.go b/volcengine/vedb_mysql/vedb_mysql_endpoint/resource_volcengine_vedb_mysql_endpoint.go new file mode 100644 index 00000000..81bad3c6 --- /dev/null +++ b/volcengine/vedb_mysql/vedb_mysql_endpoint/resource_volcengine_vedb_mysql_endpoint.go @@ -0,0 +1,228 @@ +package vedb_mysql_endpoint + +import ( + "fmt" + "strings" + "time" + + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + ve "github.com/volcengine/terraform-provider-volcengine/common" +) + +/* + +Import +VedbMysqlEndpoint can be imported using the instance id:endpoint id, e.g. +``` +$ terraform import volcengine_vedb_mysql_endpoint.default vedbm-iqnh3a7z****:vedbm-2pf2xk5v****-Custom-50yv +``` +Note: The master node endpoint only supports modifying the EndpointName and Description parameters. If values are passed in for other parameters, these values will be ignored without generating an error. +The default endpoint does not support modifying the ReadWriteMode, AutoAddNewNodes, and Nodes parameters. If values are passed in for these parameters, these values will be ignored without generating an error. +*/ + +func ResourceVolcengineVedbMysqlEndpoint() *schema.Resource { + resource := &schema.Resource{ + Create: resourceVolcengineVedbMysqlEndpointCreate, + Read: resourceVolcengineVedbMysqlEndpointRead, + Update: resourceVolcengineVedbMysqlEndpointUpdate, + Delete: resourceVolcengineVedbMysqlEndpointDelete, + Importer: &schema.ResourceImporter{ + State: vedbMysqlEndpointImporter, + }, + Timeouts: &schema.ResourceTimeout{ + Create: schema.DefaultTimeout(30 * time.Minute), + Update: schema.DefaultTimeout(30 * time.Minute), + Delete: schema.DefaultTimeout(30 * time.Minute), + }, + Schema: map[string]*schema.Schema{ + "endpoint_id": { + Type: schema.TypeString, + Computed: true, + Description: "The id of the endpoint.", + }, + "instance_id": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: "The id of the instance.", + }, + "endpoint_type": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: "Connect endpoint type. The value is fixed as Custom, indicating a custom endpoint.", + }, + "read_write_mode": { + Type: schema.TypeString, + Optional: true, + Computed: true, + Description: "Endpoint read-write mode. Values:\n ReadWrite: Read and write endpoint.\n ReadOnly: Read-only endpoint (default).", + }, + "endpoint_name": { + Type: schema.TypeString, + Optional: true, + Computed: true, + Description: "Connect the endpoint name. The setting rules are as follows:\n " + + "It cannot start with a number or a hyphen (-).\n " + + "It can only contain Chinese characters, letters, numbers, underscores (_), and hyphens (-).\n " + + "The length is 1 to 64 characters.", + }, + "description": { + Type: schema.TypeString, + Optional: true, + Description: "Description information for connecting endpoint. The length cannot exceed 200 characters.", + }, + "node_ids": { + Type: schema.TypeSet, + Required: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + Description: "Connect the node IDs associated with the endpoint." + + "The filling rules are as follows:\n" + + "When the value of ReadWriteMode is ReadWrite, at least two nodes must be passed in, and the master node must be passed in.\n" + + "When the value of ReadWriteMode is ReadOnly, one or more read-only nodes can be passed in.", + }, + // 这个不能暴露出去,要不会触发node ids变更 + //"auto_add_new_nodes": { + // Type: schema.TypeBool, + // Optional: true, + // Default: false, + // Description: "Set whether newly created read-only nodes will automatically join this connection endpoint." + + // " Values:\ntrue: Automatically join.\nfalse: Do not automatically join (default).", + //}, + "master_accept_read_requests": { + Type: schema.TypeBool, + Optional: true, + Default: true, + DiffSuppressFunc: func(k, old, new string, d *schema.ResourceData) bool { + //仅当 ReadWriteMode 取值为ReadWrite 时,支持开启主节点接受读。 + if d.Get("read_write_mode").(string) != "ReadWrite" { + return true + } + return false + }, + Description: "The master node accepts read requests. " + + "Value range:\ntrue: (default) After enabling the master node to accept read functions, " + + "non-transactional read requests will be sent to the master node or read-only nodes in a load-balanced mode according to the number of active requests." + + "\nfalse: After disabling the master node from accepting read requests, at this time," + + " the master node only accepts transactional read requests, " + + "and non-transactional read requests will not be sent to the master node.\n" + + "Description\nOnly when the value of ReadWriteMode is ReadWrite, " + + "enabling the master node to accept reads is supported.", + }, + "distributed_transaction": { + Type: schema.TypeBool, + Optional: true, + Default: true, + DiffSuppressFunc: func(k, old, new string, d *schema.ResourceData) bool { + //仅当 ReadWriteMode 取值为ReadWrite 时,支持开启事务拆分。 + if d.Get("read_write_mode").(string) != "ReadWrite" { + return true + } + return false + }, + Description: "Set whether to enable transaction splitting. " + + "For detailed introduction to transaction splitting, please refer to transaction splitting." + + " Value range:\ntrue: Enabled (default).\nfalse: Disabled.\n" + + "Description\nOnly when the value of ReadWriteMode is ReadWrite, is enabling transaction splitting supported.", + }, + "consist_level": { + Type: schema.TypeString, + Optional: true, + Computed: true, + Description: "Consistency level. " + + "For detailed introduction of consistency level, " + + "please refer to consistency level. " + + "Value range:\nEventual: eventual consistency.\n" + + "Session: session consistency.\nGlobal: global consistency.\n" + + "Description\nWhen the value of ReadWriteMode is ReadWrite, " + + "the selectable consistency levels are Eventual, Session (default), and Global." + + "\nWhen the value of ReadWriteMode is ReadOnly, the consistency level is Eventual by default and cannot be changed.", + }, + "consist_timeout": { + Type: schema.TypeInt, + Optional: true, + Computed: true, + DiffSuppressFunc: func(k, old, new string, d *schema.ResourceData) bool { + //当 ConsistLevel 取值为 Global 或 Session 时,该参数才生效。 + if d.Get("consist_level").(string) != "Global" && d.Get("consist_level").(string) != "Session" { + return true + } + return false + }, + Description: "When there is a large delay, " + + "the timeout period for read-only nodes to synchronize the latest data, in us. " + + "The value range is from 1us to 100000000us, and the default value is 10000us.\n" + + "Explanation\n This parameter takes effect only when the value of ConsistLevel is Global or Session.", + }, + "consist_timeout_action": { + Type: schema.TypeString, + Optional: true, + Computed: true, + DiffSuppressFunc: func(k, old, new string, d *schema.ResourceData) bool { + //当 ConsistLevel 取值为 Global 或 Session 时,该参数才生效。 + if d.Get("consist_level").(string) != "Global" && d.Get("consist_level").(string) != "Session" { + return true + } + return false + }, + Description: "Timeout policy after data synchronization timeout of read-only nodes supports the following two policies:" + + "\nReturnError: Return SQL error (wait replication complete timeout, please retry)." + + "\nReadMaster: Send a request to the master node (default).\n" + + "Description\n This parameter takes effect only when the value of ConsistLevel is Global or Session.", + }, + }, + } + return resource +} + +func resourceVolcengineVedbMysqlEndpointCreate(d *schema.ResourceData, meta interface{}) (err error) { + service := NewVedbMysqlEndpointService(meta.(*ve.SdkClient)) + err = service.Dispatcher.Create(service, d, ResourceVolcengineVedbMysqlEndpoint()) + if err != nil { + return fmt.Errorf("error on creating vedb_mysql_endpoint %q, %s", d.Id(), err) + } + return resourceVolcengineVedbMysqlEndpointRead(d, meta) +} + +func resourceVolcengineVedbMysqlEndpointRead(d *schema.ResourceData, meta interface{}) (err error) { + service := NewVedbMysqlEndpointService(meta.(*ve.SdkClient)) + err = service.Dispatcher.Read(service, d, ResourceVolcengineVedbMysqlEndpoint()) + if err != nil { + return fmt.Errorf("error on reading vedb_mysql_endpoint %q, %s", d.Id(), err) + } + return err +} + +func resourceVolcengineVedbMysqlEndpointUpdate(d *schema.ResourceData, meta interface{}) (err error) { + service := NewVedbMysqlEndpointService(meta.(*ve.SdkClient)) + err = service.Dispatcher.Update(service, d, ResourceVolcengineVedbMysqlEndpoint()) + if err != nil { + return fmt.Errorf("error on updating vedb_mysql_endpoint %q, %s", d.Id(), err) + } + return resourceVolcengineVedbMysqlEndpointRead(d, meta) +} + +func resourceVolcengineVedbMysqlEndpointDelete(d *schema.ResourceData, meta interface{}) (err error) { + service := NewVedbMysqlEndpointService(meta.(*ve.SdkClient)) + err = service.Dispatcher.Delete(service, d, ResourceVolcengineVedbMysqlEndpoint()) + if err != nil { + return fmt.Errorf("error on deleting vedb_mysql_endpoint %q, %s", d.Id(), err) + } + return err +} + +var vedbMysqlEndpointImporter = func(data *schema.ResourceData, i interface{}) ([]*schema.ResourceData, error) { + items := strings.Split(data.Id(), ":") + if len(items) != 2 { + return []*schema.ResourceData{data}, fmt.Errorf("import id must split with ':'") + } + if err := data.Set("instance_id", items[0]); err != nil { + return []*schema.ResourceData{data}, err + } + if err := data.Set("endpoint_id", items[1]); err != nil { + return []*schema.ResourceData{data}, err + } + return []*schema.ResourceData{data}, nil +} diff --git a/volcengine/vedb_mysql/vedb_mysql_endpoint/service_volcengine_vedb_mysql_endpoint.go b/volcengine/vedb_mysql/vedb_mysql_endpoint/service_volcengine_vedb_mysql_endpoint.go new file mode 100644 index 00000000..ba3034e6 --- /dev/null +++ b/volcengine/vedb_mysql/vedb_mysql_endpoint/service_volcengine_vedb_mysql_endpoint.go @@ -0,0 +1,360 @@ +package vedb_mysql_endpoint + +import ( + "encoding/json" + "errors" + "fmt" + "strings" + "time" + + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + ve "github.com/volcengine/terraform-provider-volcengine/common" + "github.com/volcengine/terraform-provider-volcengine/logger" + "github.com/volcengine/terraform-provider-volcengine/volcengine/vedb_mysql/vedb_mysql_instance" +) + +type VolcengineVedbMysqlEndpointService struct { + Client *ve.SdkClient + Dispatcher *ve.Dispatcher +} + +func NewVedbMysqlEndpointService(c *ve.SdkClient) *VolcengineVedbMysqlEndpointService { + return &VolcengineVedbMysqlEndpointService{ + Client: c, + Dispatcher: &ve.Dispatcher{}, + } +} + +func (s *VolcengineVedbMysqlEndpointService) GetClient() *ve.SdkClient { + return s.Client +} + +func (s *VolcengineVedbMysqlEndpointService) ReadResources(m map[string]interface{}) (data []interface{}, err error) { + var ( + resp *map[string]interface{} + results interface{} + ok bool + ) + return ve.WithSimpleQuery(m, func(condition map[string]interface{}) ([]interface{}, error) { + action := "DescribeDBEndpoint" + + bytes, _ := json.Marshal(condition) + logger.Debug(logger.ReqFormat, action, string(bytes)) + if condition == nil { + resp, err = s.Client.UniversalClient.DoCall(getUniversalInfo(action), nil) + if err != nil { + return data, err + } + } else { + resp, err = s.Client.UniversalClient.DoCall(getUniversalInfo(action), &condition) + if err != nil { + return data, err + } + } + respBytes, _ := json.Marshal(resp) + logger.Debug(logger.RespFormat, action, condition, string(respBytes)) + + results, err = ve.ObtainSdkValue("Result.Endpoints", *resp) + if err != nil { + return data, err + } + if results == nil { + results = []interface{}{} + } + if data, ok = results.([]interface{}); !ok { + return data, errors.New("Result.Endpoints is not Slice") + } + return data, err + }) +} + +func (s *VolcengineVedbMysqlEndpointService) ReadResource(resourceData *schema.ResourceData, id string) (data map[string]interface{}, err error) { + var ( + results []interface{} + ok bool + ) + if id == "" { + id = s.ReadResourceId(resourceData.Id()) + } + ids := strings.Split(id, ":") + if len(ids) != 2 { + return nil, errors.New("ids length is not correct") + } + req := map[string]interface{}{ + "InstanceId": ids[0], + "EndpointId": ids[1], + } + results, err = s.ReadResources(req) + if err != nil { + return data, err + } + for _, v := range results { + if data, ok = v.(map[string]interface{}); !ok { + return data, errors.New("Value is not map ") + } + } + if len(data) == 0 { + return data, fmt.Errorf("vedb_mysql_endpoint %s not exist ", id) + } + //// 接口有问题,endpoint创建完一段时间查询不到node ids + //if nodeIds, ok := data["NodeIds"]; !ok || nodeIds == nil || len(nodeIds.([]interface{})) == 0 { + // nodes, ok := resourceData.GetOk("node_ids") + // if !ok { + // data["NodeIds"] = []string{} + // } else { + // data["NodeIds"] = nodes.(*schema.Set).List() + // } + //} + return data, err +} + +func (s *VolcengineVedbMysqlEndpointService) RefreshResourceState(resourceData *schema.ResourceData, target []string, timeout time.Duration, id string) *resource.StateChangeConf { + return &resource.StateChangeConf{ + Pending: []string{}, + Delay: 1 * time.Second, + MinTimeout: 1 * time.Second, + Target: target, + Timeout: timeout, + Refresh: func() (result interface{}, state string, err error) { + var ( + d map[string]interface{} + status interface{} + failStates []string + ) + failStates = append(failStates, "Failed") + d, err = s.ReadResource(resourceData, id) + if err != nil { + return nil, "", err + } + status, err = ve.ObtainSdkValue("Status", d) + if err != nil { + return nil, "", err + } + for _, v := range failStates { + if v == status.(string) { + return nil, "", fmt.Errorf("vedb_mysql_endpoint status error, status: %s", status.(string)) + } + } + return d, status.(string), err + }, + } +} + +func (s *VolcengineVedbMysqlEndpointService) CreateResource(resourceData *schema.ResourceData, resource *schema.Resource) []ve.Callback { + callback := ve.Callback{ + Call: ve.SdkCall{ + Action: "CreateDBEndpoint", + ConvertMode: ve.RequestConvertAll, + ContentType: ve.ContentTypeJson, + Convert: map[string]ve.RequestConvert{ + "node_ids": { + Ignore: true, + }, + }, + BeforeCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (bool, error) { + nodeIds := d.Get("node_ids").(*schema.Set).List() + nodeList := make([]string, 0) + for _, nodeId := range nodeIds { + nodeStr := nodeId.(string) + nodeList = append(nodeList, nodeStr) + } + nodes := strings.Join(nodeList, ",") + (*call.SdkParam)["Nodes"] = nodes + return true, nil + }, + ExecuteCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (*map[string]interface{}, error) { + logger.Debug(logger.RespFormat, call.Action, call.SdkParam) + resp, err := s.Client.UniversalClient.DoCall(getUniversalInfo(call.Action), call.SdkParam) + logger.Debug(logger.RespFormat, call.Action, resp, err) + return resp, err + }, + LockId: func(d *schema.ResourceData) string { + return d.Get("instance_id").(string) + }, + AfterCall: func(d *schema.ResourceData, client *ve.SdkClient, resp *map[string]interface{}, call ve.SdkCall) error { + id, _ := ve.ObtainSdkValue("Result.EndpointId", *resp) + d.SetId(fmt.Sprint((*call.SdkParam)["InstanceId"], ":", id.(string))) + return nil + }, + ExtraRefresh: map[ve.ResourceService]*ve.StateRefresh{ + vedb_mysql_instance.NewVedbMysqlInstanceService(s.Client): { + Target: []string{"Running"}, + Timeout: resourceData.Timeout(schema.TimeoutCreate), + ResourceId: resourceData.Get("instance_id").(string), + }, + }, + }, + } + return []ve.Callback{callback} +} + +func (VolcengineVedbMysqlEndpointService) WithResourceResponseHandlers(d map[string]interface{}) []ve.ResourceResponseHandler { + handler := func() (map[string]interface{}, map[string]ve.ResponseConvert, error) { + return d, nil, nil + } + return []ve.ResourceResponseHandler{handler} +} + +func (s *VolcengineVedbMysqlEndpointService) ModifyResource(resourceData *schema.ResourceData, resource *schema.Resource) []ve.Callback { + callback := ve.Callback{ + Call: ve.SdkCall{ + Action: "ModifyDBEndpoint", + ConvertMode: ve.RequestConvertInConvert, + ContentType: ve.ContentTypeJson, + Convert: map[string]ve.RequestConvert{ + "read_write_mode": { + TargetField: "ReadWriteMode", + }, + "endpoint_name": { + TargetField: "EndpointName", + }, + "description": { + TargetField: "Description", + }, + "node_ids": { + Ignore: true, + }, + //"auto_add_new_nodes": { + // TargetField: "AutoAddNewNodes", + //}, + "master_accept_read_requests": { + TargetField: "MasterAcceptReadRequests", + }, + "distributed_transaction": { + TargetField: "DistributedTransaction", + }, + "consist_level": { + TargetField: "ConsistLevel", + }, + "consist_timeout": { + TargetField: "ConsistTimeout", + }, + "consist_timeout_action": { + TargetField: "ConsistTimeoutAction", + }, + }, + BeforeCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (bool, error) { + ids := strings.Split(d.Id(), ":") + (*call.SdkParam)["InstanceId"] = ids[0] + (*call.SdkParam)["EndpointId"] = ids[1] + if d.HasChange("node_ids") { + nodeIds := d.Get("node_ids").(*schema.Set).List() + nodeList := make([]string, 0) + for _, nodeId := range nodeIds { + nodeStr := nodeId.(string) + nodeList = append(nodeList, nodeStr) + } + nodes := strings.Join(nodeList, ",") + (*call.SdkParam)["Nodes"] = nodes + } + return true, nil + }, + LockId: func(d *schema.ResourceData) string { + return d.Get("instance_id").(string) + }, + ExecuteCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (*map[string]interface{}, error) { + logger.Debug(logger.ReqFormat, call.Action, call.SdkParam) + resp, err := s.Client.UniversalClient.DoCall(getUniversalInfo(call.Action), call.SdkParam) + logger.Debug(logger.RespFormat, call.Action, resp, err) + return resp, err + }, + ExtraRefresh: map[ve.ResourceService]*ve.StateRefresh{ + vedb_mysql_instance.NewVedbMysqlInstanceService(s.Client): { + Target: []string{"Running"}, + Timeout: resourceData.Timeout(schema.TimeoutDelete), + ResourceId: resourceData.Get("instance_id").(string), + }, + }, + }, + } + return []ve.Callback{callback} +} + +func (s *VolcengineVedbMysqlEndpointService) RemoveResource(resourceData *schema.ResourceData, r *schema.Resource) []ve.Callback { + callback := ve.Callback{ + Call: ve.SdkCall{ + Action: "DeleteDBEndpoint", + ConvertMode: ve.RequestConvertIgnore, + ContentType: ve.ContentTypeJson, + BeforeCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (bool, error) { + ids := strings.Split(d.Id(), ":") + (*call.SdkParam)["InstanceId"] = ids[0] + (*call.SdkParam)["EndpointId"] = ids[1] + return true, nil + }, + ExecuteCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (*map[string]interface{}, error) { + logger.Debug(logger.RespFormat, call.Action, call.SdkParam) + return s.Client.UniversalClient.DoCall(getUniversalInfo(call.Action), call.SdkParam) + }, + AfterCall: func(d *schema.ResourceData, client *ve.SdkClient, resp *map[string]interface{}, call ve.SdkCall) error { + return ve.CheckResourceUtilRemoved(d, s.ReadResource, 5*time.Minute) + }, + LockId: func(d *schema.ResourceData) string { + return d.Get("instance_id").(string) + }, + ExtraRefresh: map[ve.ResourceService]*ve.StateRefresh{ + vedb_mysql_instance.NewVedbMysqlInstanceService(s.Client): { + Target: []string{"Running"}, + Timeout: resourceData.Timeout(schema.TimeoutDelete), + ResourceId: resourceData.Get("instance_id").(string), + }, + }, + CallError: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall, baseErr error) error { + //出现错误后重试 + return resource.Retry(15*time.Minute, func() *resource.RetryError { + _, callErr := s.ReadResource(d, "") + if callErr != nil { + if ve.ResourceNotFoundError(callErr) { + return nil + } else { + return resource.NonRetryableError(fmt.Errorf("error on reading vedb mysql endpoint on delete %q, %w", d.Id(), callErr)) + } + } + _, callErr = call.ExecuteCall(d, client, call) + if callErr == nil { + return nil + } + return resource.RetryableError(callErr) + }) + }, + }, + } + return []ve.Callback{callback} +} + +func (s *VolcengineVedbMysqlEndpointService) DatasourceResources(*schema.ResourceData, *schema.Resource) ve.DataSourceInfo { + return ve.DataSourceInfo{ + RequestConverts: map[string]ve.RequestConvert{}, + NameField: "EndpointName", + IdField: "EndpointId", + CollectField: "endpoints", + ContentType: ve.ContentTypeJson, + ResponseConverts: map[string]ve.ResponseConvert{ + "EndpointId": { + TargetField: "id", + KeepDefault: true, + }, + "DNSVisibility": { + TargetField: "dns_visibility", + }, + "IPAddress": { + TargetField: "ip_address", + }, + }, + } +} + +func (s *VolcengineVedbMysqlEndpointService) ReadResourceId(id string) string { + return id +} + +func getUniversalInfo(actionName string) ve.UniversalInfo { + return ve.UniversalInfo{ + ServiceName: "vedbm", + Version: "2022-01-01", + HttpMethod: ve.POST, + ContentType: ve.ApplicationJSON, + Action: actionName, + } +} diff --git a/volcengine/vedb_mysql/vedb_mysql_endpoint_public_address/resource_volcengine_vedb_mysql_endpoint_public_address.go b/volcengine/vedb_mysql/vedb_mysql_endpoint_public_address/resource_volcengine_vedb_mysql_endpoint_public_address.go new file mode 100644 index 00000000..7e3e25a0 --- /dev/null +++ b/volcengine/vedb_mysql/vedb_mysql_endpoint_public_address/resource_volcengine_vedb_mysql_endpoint_public_address.go @@ -0,0 +1,100 @@ +package vedb_mysql_endpoint_public_address + +import ( + "fmt" + "strings" + "time" + + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + ve "github.com/volcengine/terraform-provider-volcengine/common" +) + +/* + +Import +VedbMysqlEndpointPublicAddress can be imported using the instance id, endpoint id and the eip id, e.g. +``` +$ terraform import volcengine_vedb_mysql_endpoint_public_address.default vedbm-iqnh3a7z****:vedbm-2pf2xk5v****-Custom-50yv:eip-xxxx +``` + +*/ + +func ResourceVolcengineVedbMysqlEndpointPublicAddress() *schema.Resource { + resource := &schema.Resource{ + Create: resourceVolcengineVedbMysqlEndpointPublicAddressCreate, + Read: resourceVolcengineVedbMysqlEndpointPublicAddressRead, + Delete: resourceVolcengineVedbMysqlEndpointPublicAddressDelete, + Importer: &schema.ResourceImporter{ + State: vedbMysqlEndpointAssociateImporter, + }, + Timeouts: &schema.ResourceTimeout{ + Create: schema.DefaultTimeout(30 * time.Minute), + Delete: schema.DefaultTimeout(30 * time.Minute), + }, + Schema: map[string]*schema.Schema{ + "instance_id": { + Type: schema.TypeString, + ForceNew: true, + Required: true, + Description: "The instance id.", + }, + "endpoint_id": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: "The endpoint id.", + }, + "eip_id": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: "EIP ID that needs to be bound to the instance.", + }, + }, + } + return resource +} + +func resourceVolcengineVedbMysqlEndpointPublicAddressCreate(d *schema.ResourceData, meta interface{}) (err error) { + service := NewVedbMysqlEndpointPublicAddressService(meta.(*ve.SdkClient)) + err = service.Dispatcher.Create(service, d, ResourceVolcengineVedbMysqlEndpointPublicAddress()) + if err != nil { + return fmt.Errorf("error on creating vedb_mysql_endpoint_public_address %q, %s", d.Id(), err) + } + return resourceVolcengineVedbMysqlEndpointPublicAddressRead(d, meta) +} + +func resourceVolcengineVedbMysqlEndpointPublicAddressRead(d *schema.ResourceData, meta interface{}) (err error) { + service := NewVedbMysqlEndpointPublicAddressService(meta.(*ve.SdkClient)) + err = service.Dispatcher.Read(service, d, ResourceVolcengineVedbMysqlEndpointPublicAddress()) + if err != nil { + return fmt.Errorf("error on reading vedb_mysql_endpoint_public_address %q, %s", d.Id(), err) + } + return err +} + +func resourceVolcengineVedbMysqlEndpointPublicAddressDelete(d *schema.ResourceData, meta interface{}) (err error) { + service := NewVedbMysqlEndpointPublicAddressService(meta.(*ve.SdkClient)) + err = service.Dispatcher.Delete(service, d, ResourceVolcengineVedbMysqlEndpointPublicAddress()) + if err != nil { + return fmt.Errorf("error on deleting vedb_mysql_endpoint_public_address %q, %s", d.Id(), err) + } + return err +} + +var vedbMysqlEndpointAssociateImporter = func(data *schema.ResourceData, i interface{}) ([]*schema.ResourceData, error) { + items := strings.Split(data.Id(), ":") + if len(items) != 3 { + return []*schema.ResourceData{data}, fmt.Errorf("import id must split with ':'") + } + if err := data.Set("instance_id", items[0]); err != nil { + return []*schema.ResourceData{data}, err + } + if err := data.Set("endpoint_id", items[1]); err != nil { + return []*schema.ResourceData{data}, err + } + if err := data.Set("eip_id", items[2]); err != nil { + return []*schema.ResourceData{data}, err + } + return []*schema.ResourceData{data}, nil +} diff --git a/volcengine/vedb_mysql/vedb_mysql_endpoint_public_address/service_volcengine_vedb_mysql_endpoint_public_address.go b/volcengine/vedb_mysql/vedb_mysql_endpoint_public_address/service_volcengine_vedb_mysql_endpoint_public_address.go new file mode 100644 index 00000000..d5b68984 --- /dev/null +++ b/volcengine/vedb_mysql/vedb_mysql_endpoint_public_address/service_volcengine_vedb_mysql_endpoint_public_address.go @@ -0,0 +1,255 @@ +package vedb_mysql_endpoint_public_address + +import ( + "encoding/json" + "errors" + "fmt" + "strings" + "time" + + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + ve "github.com/volcengine/terraform-provider-volcengine/common" + "github.com/volcengine/terraform-provider-volcengine/logger" + "github.com/volcengine/terraform-provider-volcengine/volcengine/eip/eip_address" + "github.com/volcengine/terraform-provider-volcengine/volcengine/vedb_mysql/vedb_mysql_instance" +) + +type VolcengineVedbMysqlEndpointPublicAddressService struct { + Client *ve.SdkClient + Dispatcher *ve.Dispatcher +} + +func NewVedbMysqlEndpointPublicAddressService(c *ve.SdkClient) *VolcengineVedbMysqlEndpointPublicAddressService { + return &VolcengineVedbMysqlEndpointPublicAddressService{ + Client: c, + Dispatcher: &ve.Dispatcher{}, + } +} + +func (s *VolcengineVedbMysqlEndpointPublicAddressService) GetClient() *ve.SdkClient { + return s.Client +} + +func (s *VolcengineVedbMysqlEndpointPublicAddressService) ReadResources(m map[string]interface{}) (data []interface{}, err error) { + var ( + resp *map[string]interface{} + results interface{} + ok bool + ) + return ve.WithSimpleQuery(m, func(condition map[string]interface{}) ([]interface{}, error) { + action := "DescribeDBEndpoint" + + bytes, _ := json.Marshal(condition) + logger.Debug(logger.ReqFormat, action, string(bytes)) + if condition == nil { + resp, err = s.Client.UniversalClient.DoCall(getUniversalInfo(action), nil) + if err != nil { + return data, err + } + } else { + resp, err = s.Client.UniversalClient.DoCall(getUniversalInfo(action), &condition) + if err != nil { + return data, err + } + } + respBytes, _ := json.Marshal(resp) + logger.Debug(logger.RespFormat, action, condition, string(respBytes)) + + results, err = ve.ObtainSdkValue("Result.Endpoints", *resp) + if err != nil { + return data, err + } + if results == nil { + results = []interface{}{} + } + if data, ok = results.([]interface{}); !ok { + return data, errors.New("Result.Endpoints is not Slice") + } + return data, err + }) +} + +func (s *VolcengineVedbMysqlEndpointPublicAddressService) ReadResource(resourceData *schema.ResourceData, id string) (data map[string]interface{}, err error) { + var ( + results []interface{} + tmpData map[string]interface{} + ok bool + ) + if id == "" { + id = s.ReadResourceId(resourceData.Id()) + } + ids := strings.Split(id, ":") + if len(ids) != 3 { + return nil, errors.New("ids length is not correct") + } + req := map[string]interface{}{ + "InstanceId": ids[0], + "EndpointId": ids[1], + } + results, err = s.ReadResources(req) + if err != nil { + return data, err + } + for _, v := range results { + if tmpData, ok = v.(map[string]interface{}); !ok { + return tmpData, errors.New("Value is not map ") + } + } + if len(tmpData) == 0 { + return data, fmt.Errorf("vedb_mysql_allowlist_associate %s not exist ", id) + } + addresses := tmpData["Addresses"] + if a, ok := addresses.([]interface{}); ok && len(addresses.([]interface{})) > 0 { + for _, add := range a { + addMap := add.(map[string]interface{}) + if addMap["EipId"] == ids[2] { + data = addMap + } + } + } + if len(data) == 0 { + return data, fmt.Errorf("vedb_mysql_allowlist_associate %s not exist ", id) + } + data["EndpointId"] = ids[1] + data["InstanceId"] = ids[0] + return data, err +} + +func (s *VolcengineVedbMysqlEndpointPublicAddressService) RefreshResourceState(resourceData *schema.ResourceData, target []string, timeout time.Duration, id string) *resource.StateChangeConf { + return &resource.StateChangeConf{ + Pending: []string{}, + Delay: 1 * time.Second, + MinTimeout: 1 * time.Second, + Target: target, + Timeout: timeout, + Refresh: func() (result interface{}, state string, err error) { + var ( + d map[string]interface{} + status interface{} + failStates []string + ) + failStates = append(failStates, "Failed") + d, err = s.ReadResource(resourceData, id) + if err != nil { + return nil, "", err + } + status, err = ve.ObtainSdkValue("Status", d) + if err != nil { + return nil, "", err + } + for _, v := range failStates { + if v == status.(string) { + return nil, "", fmt.Errorf("vedb_mysql_endpoint_public_address status error, status: %s", status.(string)) + } + } + return d, status.(string), err + }, + } +} + +func (s *VolcengineVedbMysqlEndpointPublicAddressService) CreateResource(resourceData *schema.ResourceData, resource *schema.Resource) []ve.Callback { + callback := ve.Callback{ + Call: ve.SdkCall{ + Action: "CreateDBEndpointPublicAddress", + ConvertMode: ve.RequestConvertAll, + ContentType: ve.ContentTypeJson, + Convert: map[string]ve.RequestConvert{}, + ExecuteCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (*map[string]interface{}, error) { + logger.Debug(logger.RespFormat, call.Action, call.SdkParam) + resp, err := s.Client.UniversalClient.DoCall(getUniversalInfo(call.Action), call.SdkParam) + logger.Debug(logger.RespFormat, call.Action, resp, err) + return resp, err + }, + AfterCall: func(d *schema.ResourceData, client *ve.SdkClient, resp *map[string]interface{}, call ve.SdkCall) error { + d.SetId(fmt.Sprint((*call.SdkParam)["InstanceId"], ":", (*call.SdkParam)["EndpointId"], ":", (*call.SdkParam)["EipId"])) + return nil + }, + LockId: func(d *schema.ResourceData) string { + return d.Get("instance_id").(string) + }, + ExtraRefresh: map[ve.ResourceService]*ve.StateRefresh{ + vedb_mysql_instance.NewVedbMysqlInstanceService(s.Client): { + Target: []string{"Running"}, + Timeout: resourceData.Timeout(schema.TimeoutDelete), + ResourceId: resourceData.Get("instance_id").(string), + }, + eip_address.NewEipAddressService(s.Client): { + Target: []string{"Attached"}, + Timeout: resourceData.Timeout(schema.TimeoutDelete), + ResourceId: resourceData.Get("eip_id").(string), + }, + }, + }, + } + return []ve.Callback{callback} +} + +func (VolcengineVedbMysqlEndpointPublicAddressService) WithResourceResponseHandlers(d map[string]interface{}) []ve.ResourceResponseHandler { + handler := func() (map[string]interface{}, map[string]ve.ResponseConvert, error) { + return d, nil, nil + } + return []ve.ResourceResponseHandler{handler} +} + +func (s *VolcengineVedbMysqlEndpointPublicAddressService) ModifyResource(resourceData *schema.ResourceData, resource *schema.Resource) []ve.Callback { + callback := ve.Callback{} + return []ve.Callback{callback} +} + +func (s *VolcengineVedbMysqlEndpointPublicAddressService) RemoveResource(resourceData *schema.ResourceData, r *schema.Resource) []ve.Callback { + callback := ve.Callback{ + Call: ve.SdkCall{ + Action: "DeleteDBEndpointPublicAddress", + ConvertMode: ve.RequestConvertIgnore, + ContentType: ve.ContentTypeJson, + BeforeCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (bool, error) { + ids := strings.Split(d.Id(), ":") + (*call.SdkParam)["InstanceId"] = ids[0] + (*call.SdkParam)["EndpointId"] = ids[1] + return true, nil + }, + ExecuteCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (*map[string]interface{}, error) { + logger.Debug(logger.RespFormat, call.Action, call.SdkParam) + return s.Client.UniversalClient.DoCall(getUniversalInfo(call.Action), call.SdkParam) + }, + AfterCall: func(d *schema.ResourceData, client *ve.SdkClient, resp *map[string]interface{}, call ve.SdkCall) error { + return ve.CheckResourceUtilRemoved(d, s.ReadResource, 5*time.Minute) + }, + LockId: func(d *schema.ResourceData) string { + return d.Get("instance_id").(string) + }, + ExtraRefresh: map[ve.ResourceService]*ve.StateRefresh{ + vedb_mysql_instance.NewVedbMysqlInstanceService(s.Client): { + Target: []string{"Running"}, + Timeout: resourceData.Timeout(schema.TimeoutDelete), + ResourceId: resourceData.Get("instance_id").(string), + }, + eip_address.NewEipAddressService(s.Client): { + Target: []string{"Available"}, + Timeout: resourceData.Timeout(schema.TimeoutDelete), + ResourceId: resourceData.Get("eip_id").(string), + }, + }, + }, + } + return []ve.Callback{callback} +} + +func (s *VolcengineVedbMysqlEndpointPublicAddressService) DatasourceResources(*schema.ResourceData, *schema.Resource) ve.DataSourceInfo { + return ve.DataSourceInfo{} +} + +func (s *VolcengineVedbMysqlEndpointPublicAddressService) ReadResourceId(id string) string { + return id +} + +func getUniversalInfo(actionName string) ve.UniversalInfo { + return ve.UniversalInfo{ + ServiceName: "vedbm", + Version: "2022-01-01", + HttpMethod: ve.POST, + ContentType: ve.ApplicationJSON, + Action: actionName, + } +} diff --git a/volcengine/vedb_mysql/vedb_mysql_instance/data_source_volcengine_vedb_mysql_instances.go b/volcengine/vedb_mysql/vedb_mysql_instance/data_source_volcengine_vedb_mysql_instances.go new file mode 100644 index 00000000..55abaf31 --- /dev/null +++ b/volcengine/vedb_mysql/vedb_mysql_instance/data_source_volcengine_vedb_mysql_instances.go @@ -0,0 +1,251 @@ +package vedb_mysql_instance + +import ( + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/helper/validation" + ve "github.com/volcengine/terraform-provider-volcengine/common" +) + +func DataSourceVolcengineVedbMysqlInstances() *schema.Resource { + return &schema.Resource{ + Read: dataSourceVolcengineVedbMysqlInstancesRead, + Schema: map[string]*schema.Schema{ + "instance_id": { + Type: schema.TypeString, + Optional: true, + Description: "The id of the veDB Mysql instance.", + }, + "instance_name": { + Type: schema.TypeString, + Optional: true, + Description: "The name of the veDB Mysql instance.", + }, + "instance_status": { + Type: schema.TypeString, + Optional: true, + Description: "The status of the veDB Mysql instance.", + }, + "db_engine_version": { + Type: schema.TypeString, + Optional: true, + Description: "The version of the veDB Mysql instance.", + }, + "create_time_start": { + Type: schema.TypeString, + Optional: true, + Description: "The start time of creating veDB Mysql instance.", + }, + "create_time_end": { + Type: schema.TypeString, + Optional: true, + Description: "The end time of creating veDB Mysql instance.", + }, + "zone_id": { + Type: schema.TypeString, + Optional: true, + Description: "The available zone of the veDB Mysql instance.", + }, + "charge_type": { + Type: schema.TypeString, + Optional: true, + Description: "The charge type of the veDB Mysql instance.", + }, + "tags": ve.TagsSchema(), + "project_name": { + Type: schema.TypeString, + Optional: true, + Description: "The project name of the veDB Mysql instance.", + }, + "name_regex": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.StringIsValidRegExp, + Description: "A Name Regex of veDB mysql instance.", + }, + "output_file": { + Type: schema.TypeString, + Optional: true, + Description: "File name where to save data source results.", + }, + "total_count": { + Type: schema.TypeInt, + Computed: true, + Description: "The total count of query.", + }, + "instances": { + Description: "The collection of query.", + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "id": { + Type: schema.TypeString, + Computed: true, + Description: "The ID of the veDB Mysql instance.", + }, + "instance_id": { + Type: schema.TypeString, + Computed: true, + Description: "The ID of the veDB Mysql instance.", + }, + "instance_name": { + Type: schema.TypeString, + Computed: true, + Description: "The name of the veDB Mysql instance.", + }, + "instance_status": { + Type: schema.TypeString, + Computed: true, + Description: "The status of the veDB Mysql instance.", + }, + "create_time": { + Type: schema.TypeString, + Computed: true, + Description: "The create time of the veDB Mysql instance.", + }, + "db_engine_version": { + Type: schema.TypeString, + Computed: true, + Description: "The engine version of the veDB Mysql instance.", + }, + "project_name": { + Type: schema.TypeString, + Computed: true, + Description: "The project name of the veDB Mysql instance.", + }, + "zone_ids": { + Type: schema.TypeString, + Computed: true, + Description: "The available zone of the veDB Mysql instance.", + }, + "vpc_id": { + Type: schema.TypeString, + Computed: true, + Description: "The vpc ID of the veDB Mysql instance.", + }, + "subnet_id": { + Type: schema.TypeString, + Computed: true, + Description: "The subnet ID of the veDB Mysql instance.", + }, + "time_zone": { + Type: schema.TypeString, + Computed: true, + Description: "Time zone.", + }, + "lower_case_table_names": { + Type: schema.TypeString, + Computed: true, + Description: "Whether the table name is case sensitive, the default value is 1.\nRanges:\n0: Table names are stored as fixed and table names are case-sensitive.\n1: Table names will be stored in lowercase and table names are not case sensitive.", + }, + "tags": ve.TagsSchemaComputed(), + "storage_charge_type": { + Type: schema.TypeString, + Computed: true, + Description: "Storage billing type. " + + "Values:\nPostPaid: Pay-as-you-go (postpaid).\n" + + "PrePaid: Monthly/yearly subscription (prepaid).", + }, + "pre_paid_storage_in_gb": { + Type: schema.TypeInt, + Computed: true, + Description: "Total storage capacity in GiB for prepaid services.", + }, + "storage_used_gib": { + Type: schema.TypeFloat, + Computed: true, + Description: "Used storage size, unit: GiB.", + }, + "region_id": { + Type: schema.TypeString, + Computed: true, + Description: "The region id.", + }, + "charge_type": { + Type: schema.TypeString, + Computed: true, + Description: "Calculate the billing type. Values:\n" + + "PostPaid: Pay-as-you-go (postpaid).\n" + + "PrePaid: Monthly/yearly subscription (prepaid).", + }, + "charge_status": { + Type: schema.TypeString, + Computed: true, + Description: "Payment status:\nNormal: Normal.\nOverdue: In arrears.\nShutdown: Shut down.", + }, + "overdue_reclaim_time": { + Type: schema.TypeString, + Computed: true, + Description: "Expected release time when shut down due to arrears. Format: yyyy-MM-ddTHH:mm:ssZ (UTC time).", + }, + "overdue_time": { + Type: schema.TypeString, + Computed: true, + Description: "Overdue shutdown time. Format: yyyy-MM-ddTHH:mm:ssZ (UTC time).", + }, + "auto_renew": { + Type: schema.TypeBool, + Computed: true, + Description: "Whether auto-renewal is enabled in the prepaid scenario. " + + "Values:\ntrue: Auto-renewal is enabled.\nfalse: Auto-renewal is not enabled.", + }, + "charge_start_time": { + Type: schema.TypeString, + Computed: true, + Description: "The time when billing starts. Format: yyyy-MM-ddTHH:mm:ssZ (UTC time).", + }, + "charge_end_time": { + Type: schema.TypeString, + Computed: true, + Description: "The billing expiration time in the prepaid scenario, in the format: yyyy-MM-ddTHH:mm:ssZ (UTC time).", + }, + "nodes": { + Type: schema.TypeList, + Computed: true, + Description: "Detailed information of instance nodes.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "node_id": { + Type: schema.TypeString, + Computed: true, + Description: "The id of the node.", + }, + "zone_id": { + Type: schema.TypeString, + Computed: true, + Description: "The zone id.", + }, + "node_type": { + Type: schema.TypeString, + Computed: true, + Description: "Node type. Values:\nPrimary: Primary node.\nReadOnly: Read-only node.", + }, + "v_cpu": { + Type: schema.TypeInt, + Computed: true, + Description: "CPU size. For example, when the value is 1, it means the CPU size is 1U.", + }, + "memory": { + Type: schema.TypeInt, + Computed: true, + Description: "Memory size, in GiB.", + }, + "node_spec": { + Type: schema.TypeString, + Computed: true, + Description: "Node specification of an instance.", + }, + }, + }, + }, + }, + }, + }, + }, + } +} + +func dataSourceVolcengineVedbMysqlInstancesRead(d *schema.ResourceData, meta interface{}) error { + service := NewVedbMysqlInstanceService(meta.(*ve.SdkClient)) + return service.Dispatcher.Data(service, d, DataSourceVolcengineVedbMysqlInstances()) +} diff --git a/volcengine/vedb_mysql/vedb_mysql_instance/resource_volcengine_vedb_mysql_instance.go b/volcengine/vedb_mysql/vedb_mysql_instance/resource_volcengine_vedb_mysql_instance.go new file mode 100644 index 00000000..3563e747 --- /dev/null +++ b/volcengine/vedb_mysql/vedb_mysql_instance/resource_volcengine_vedb_mysql_instance.go @@ -0,0 +1,240 @@ +package vedb_mysql_instance + +import ( + "fmt" + "time" + + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + ve "github.com/volcengine/terraform-provider-volcengine/common" +) + +/* + +Import +VedbMysqlInstance can be imported using the id, e.g. +``` +$ terraform import volcengine_vedb_mysql_instance.default resource_id +``` + +*/ + +func ResourceVolcengineVedbMysqlInstance() *schema.Resource { + resource := &schema.Resource{ + Create: resourceVolcengineVedbMysqlInstanceCreate, + Read: resourceVolcengineVedbMysqlInstanceRead, + Update: resourceVolcengineVedbMysqlInstanceUpdate, + Delete: resourceVolcengineVedbMysqlInstanceDelete, + Importer: &schema.ResourceImporter{ + State: schema.ImportStatePassthrough, + }, + Timeouts: &schema.ResourceTimeout{ + Create: schema.DefaultTimeout(60 * time.Minute), + Update: schema.DefaultTimeout(60 * time.Minute), + Delete: schema.DefaultTimeout(60 * time.Minute), + }, + Schema: map[string]*schema.Schema{ + "db_engine_version": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: "Database engine version, with a fixed value of MySQL_8_0.", + }, + "db_minor_version": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Description: "veDB MySQL minor version. For detailed instructions on version numbers, please refer to Version Number Management.\n " + + "3.0 (default): veDB MySQL stable version, 100% compatible with MySQL 8.0.\n " + + "3.1: Natively supports HTAP application scenarios and accelerates complex queries.\n " + + "3.2: Natively supports HTAP application scenarios and accelerates complex queries. " + + "In addition, it has built-in cold data archiving capabilities. " + + "It can archive data with low-frequency access to object storage TOS to reduce storage costs.", + }, + "node_spec": { + Type: schema.TypeString, + Required: true, + Description: "Node specification code of an instance.", + }, + "node_number": { + Type: schema.TypeInt, + Required: true, + Description: "Number of instance nodes. The value range is from 2 to 16.", + }, + "subnet_id": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: "Subnet ID of the veDB Mysql instance.", + }, + "port": { + Type: schema.TypeInt, + Optional: true, + Computed: true, + // 2024-10-16 当前只支持通过控制台修改端口号,api不支持修改 + ForceNew: true, + Description: "Specify the private network port number for the connection terminal created by default for the instance." + + " The default value is 3306, and the value range is 1000 to 65534.\n" + + "Note:\nThis configuration item is only effective for the primary node terminal, default terminal, " + + "and HTAP cluster terminal. That is, after the instance is created successfully," + + " for the newly created custom terminal, the port number is still 3306 by default.\n" + + "After the instance is created successfully, you can also modify the port number at any time. " + + "Currently, only modification through the console is supported.", + }, + // 超级账号功能放到account里,这里不暴露账号相关字段 + //"super_account_name": { + // + //}, + "charge_type": { + Type: schema.TypeString, + Required: true, + Description: "Calculate the billing type. When calculating the billing type during instance creation, " + + "the possible values are as follows:\n" + + "PostPaid: Pay-as-you-go (postpaid).\n" + + "PrePaid: Monthly or yearly subscription (prepaid).", + }, + "storage_charge_type": { + Type: schema.TypeString, + Optional: true, + Computed: true, + Description: "Storage billing type. " + + "When this parameter is not passed, the storage billing type defaults to be the same as the computing billing type. " + + "The values are as follows:\n" + + "PostPaid: Pay-as-you-go (postpaid).\n" + + "PrePaid: Monthly or yearly subscription (prepaid)." + + "\nNote\nWhen the computing billing type is PostPaid, " + + "the storage billing type can only be PostPaid.\n" + + "When the computing billing type is PrePaid, " + + "the storage billing type can be PrePaid or PostPaid.", + }, + "instance_name": { + Type: schema.TypeString, + Optional: true, + Computed: true, + Description: "Instance name. " + + "Naming rules:\n" + + "It cannot start with a number or a hyphen (-).\n" + + "It can only contain Chinese characters, letters, numbers, underscores (_), and hyphens (-).\n" + + "The length must be within 1 to 128 characters.\n" + + "Description\nIf the instance name is not filled in, the instance ID will be used as the instance name.\n" + + "When creating instances in batches, if an instance name is passed in, " + + "a serial number will be automatically added after the instance name.", + }, + "db_time_zone": { + Type: schema.TypeString, + Optional: true, + Computed: true, + ForceNew: true, + Description: "Time zone. Support UTC -12:00 ~ +13:00. When importing resources, this attribute will not be imported. If this attribute is set, please use lifecycle and ignore_changes ignore changes in fields.", + }, + "lower_case_table_names": { + Type: schema.TypeString, + Computed: true, + Optional: true, + ForceNew: true, + Description: "Whether table names are case-sensitive. " + + "The default value is 1. Value range:\n" + + "0: Table names are case-sensitive. The backend stores them according to the actual table name." + + "\n1: (default) Table names are not case-sensitive. " + + "The backend stores them by converting table names to lowercase letters.\n" + + "Description:\nThis rule cannot be modified after creating an instance." + + " Please set it reasonably according to business requirements.", + }, + "project_name": { + Type: schema.TypeString, + Optional: true, + Computed: true, + Description: "Project name of the instance. When this parameter is left blank, the newly created instance is added to the default project by default.", + }, + "tags": ve.TagsSchema(), + "auto_renew": { + Type: schema.TypeBool, + Optional: true, + Computed: true, + DiffSuppressFunc: VeDBMysqlInstanceImportDiffSuppress, + Description: "Whether to automatically renew under the prepaid scenario. " + + "Values:\ntrue: Automatically renew.\nfalse: Do not automatically renew.\n" + + "Description:\nWhen the value of ChargeType (billing type) is PrePaid (monthly/yearly package), " + + "this parameter is required.", + }, + "period_unit": { + Type: schema.TypeString, + Optional: true, + Computed: true, + DiffSuppressFunc: VeDBMysqlInstanceImportDiffSuppress, + Description: "Purchase cycle in prepaid scenarios.\n" + + "Month: Monthly package.\nYear: Annual package.\nDescription:\n" + + "When the value of ChargeType (computing billing type) is PrePaid (monthly or annual package), this parameter is required.", + }, + "period": { + Type: schema.TypeInt, + Optional: true, + Computed: true, + DiffSuppressFunc: VeDBMysqlInstanceImportDiffSuppress, + Description: "Purchase duration in prepaid scenarios.\n" + + "Description:\nWhen the value of ChargeType (computing billing type) is PrePaid (monthly/yearly package), " + + "this parameter is required.", + }, + "pre_paid_storage_in_gb": { + //PrePaidStorageInGB + Type: schema.TypeInt, + Optional: true, + Computed: true, + DiffSuppressFunc: func(k, old, new string, d *schema.ResourceData) bool { + if d.Get("storage_charge_type").(string) == "PostPaid" && k == "pre_paid_storage_in_gb" { + return true + } + return false + }, + Description: "Storage size in prepaid scenarios.\n" + + "Description: When the value of StorageChargeType (storage billing type) is PrePaid (monthly/yearly prepaid), " + + "this parameter is required.", + }, + }, + } + return resource +} + +func resourceVolcengineVedbMysqlInstanceCreate(d *schema.ResourceData, meta interface{}) (err error) { + service := NewVedbMysqlInstanceService(meta.(*ve.SdkClient)) + err = service.Dispatcher.Create(service, d, ResourceVolcengineVedbMysqlInstance()) + if err != nil { + return fmt.Errorf("error on creating vedb_mysql_instance %q, %s", d.Id(), err) + } + return resourceVolcengineVedbMysqlInstanceRead(d, meta) +} + +func resourceVolcengineVedbMysqlInstanceRead(d *schema.ResourceData, meta interface{}) (err error) { + service := NewVedbMysqlInstanceService(meta.(*ve.SdkClient)) + err = service.Dispatcher.Read(service, d, ResourceVolcengineVedbMysqlInstance()) + if err != nil { + return fmt.Errorf("error on reading vedb_mysql_instance %q, %s", d.Id(), err) + } + return err +} + +func resourceVolcengineVedbMysqlInstanceUpdate(d *schema.ResourceData, meta interface{}) (err error) { + service := NewVedbMysqlInstanceService(meta.(*ve.SdkClient)) + err = service.Dispatcher.Update(service, d, ResourceVolcengineVedbMysqlInstance()) + if err != nil { + return fmt.Errorf("error on updating vedb_mysql_instance %q, %s", d.Id(), err) + } + return resourceVolcengineVedbMysqlInstanceRead(d, meta) +} + +func resourceVolcengineVedbMysqlInstanceDelete(d *schema.ResourceData, meta interface{}) (err error) { + service := NewVedbMysqlInstanceService(meta.(*ve.SdkClient)) + err = service.Dispatcher.Delete(service, d, ResourceVolcengineVedbMysqlInstance()) + if err != nil { + return fmt.Errorf("error on deleting vedb_mysql_instance %q, %s", d.Id(), err) + } + return err +} + +func VeDBMysqlInstanceImportDiffSuppress(k, old, new string, d *schema.ResourceData) bool { + //在计费方式为PostPaid的时候 period的变化会被忽略 + if d.Get("charge_type").(string) == "PostPaid" && (k == "period" || k == "period_unit" || k == "auto_renew") { + return true + } + + return false +} diff --git a/volcengine/vedb_mysql/vedb_mysql_instance/service_volcengine_vedb_mysql_instance.go b/volcengine/vedb_mysql/vedb_mysql_instance/service_volcengine_vedb_mysql_instance.go new file mode 100644 index 00000000..a56189fe --- /dev/null +++ b/volcengine/vedb_mysql/vedb_mysql_instance/service_volcengine_vedb_mysql_instance.go @@ -0,0 +1,607 @@ +package vedb_mysql_instance + +import ( + "encoding/json" + "errors" + "fmt" + "time" + + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + ve "github.com/volcengine/terraform-provider-volcengine/common" + "github.com/volcengine/terraform-provider-volcengine/logger" +) + +type VolcengineVedbMysqlInstanceService struct { + Client *ve.SdkClient + Dispatcher *ve.Dispatcher +} + +func NewVedbMysqlInstanceService(c *ve.SdkClient) *VolcengineVedbMysqlInstanceService { + return &VolcengineVedbMysqlInstanceService{ + Client: c, + Dispatcher: &ve.Dispatcher{}, + } +} + +func (s *VolcengineVedbMysqlInstanceService) GetClient() *ve.SdkClient { + return s.Client +} + +func (s *VolcengineVedbMysqlInstanceService) ReadResources(m map[string]interface{}) (data []interface{}, err error) { + var ( + resp *map[string]interface{} + results interface{} + ok bool + ) + return ve.WithPageNumberQuery(m, "PageSize", "PageNumber", 100, 1, func(condition map[string]interface{}) ([]interface{}, error) { + action := "DescribeDBInstances" + + bytes, _ := json.Marshal(condition) + logger.Debug(logger.ReqFormat, action, string(bytes)) + if condition == nil { + resp, err = s.Client.UniversalClient.DoCall(getUniversalInfo(action), nil) + if err != nil { + return data, err + } + } else { + resp, err = s.Client.UniversalClient.DoCall(getUniversalInfo(action), &condition) + if err != nil { + return data, err + } + } + respBytes, _ := json.Marshal(resp) + logger.Debug(logger.RespFormat, action, condition, string(respBytes)) + + results, err = ve.ObtainSdkValue("Result.Instances", *resp) + if err != nil { + return data, err + } + if results == nil { + results = []interface{}{} + } + if data, ok = results.([]interface{}); !ok { + return data, errors.New("Result.Instances is not Slice") + } + // 拆charge信息出来 + // append detail + for _, v := range data { + var ( + detailErr error + endpointInfo interface{} + detailInfo interface{} + ) + instance := v.(map[string]interface{}) + charge, ok := instance["ChargeDetail"] + if !ok { + continue + } + if chargeMap, ok := charge.(map[string]interface{}); ok { + instance["ChargeType"] = chargeMap["ChargeType"] + instance["ChargeStatus"] = chargeMap["ChargeStatus"] + instance["OverdueReclaimTime"] = chargeMap["OverdueReclaimTime"] + instance["OverdueTime"] = chargeMap["OverdueTime"] + instance["AutoRenew"] = chargeMap["AutoRenew"] + instance["ChargeStartTime"] = chargeMap["ChargeStartTime"] + instance["ChargeEndTime"] = chargeMap["ChargeEndTime"] + } + if nodes, ok := instance["Nodes"]; ok { + if nodeList, ok := nodes.([]interface{}); ok && len(nodeList) > 0 { + nodeNum := len(nodeList) + nodeSpec := nodeList[0].(map[string]interface{})["NodeSpec"] + instance["NodeNumber"] = nodeNum + instance["NodeSpec"] = nodeSpec + } + } + + action = "DescribeDBInstanceDetail" + req := map[string]interface{}{ + "InstanceId": instance["InstanceId"], + } + resp, detailErr = s.Client.UniversalClient.DoCall(getUniversalInfo(action), &req) + if detailErr != nil { + logger.Info("DescribeDBInstanceDetail error:", detailErr) + continue + } + respBytes, _ = json.Marshal(resp) + logger.Debug(logger.RespFormat, action, req, string(respBytes)) + + // append endpoint info + endpointInfo, detailErr = ve.ObtainSdkValue("Result.Endpoints", *resp) + if detailErr != nil { + logger.Info("ObtainSdkValue Result.Endpoints error:", detailErr) + continue + } + if infos, ok := endpointInfo.([]interface{}); ok { + instance["Endpoints"] = infos + } else { + // 接口返回nil + instance["Endpoints"] = []interface{}{} + } + + detailInfo, detailErr = ve.ObtainSdkValue("Result.InstanceDetail", *resp) + if detailErr != nil { + logger.Info("ObtainSdkValue Result.InstanceDetail error:", detailErr) + continue + } + if infos, ok := detailInfo.(map[string]interface{}); ok { + instance["InstanceDetail"] = infos + } else { + // 接口返回nil + instance["InstanceDetail"] = map[string]interface{}{} + } + } + + return data, err + }) +} + +func (s *VolcengineVedbMysqlInstanceService) ReadResource(resourceData *schema.ResourceData, id string) (data map[string]interface{}, err error) { + var ( + results []interface{} + ok bool + ) + if id == "" { + id = s.ReadResourceId(resourceData.Id()) + } + req := map[string]interface{}{ + "InstanceId": id, + } + results, err = s.ReadResources(req) + if err != nil { + return data, err + } + for _, v := range results { + if data, ok = v.(map[string]interface{}); !ok { + return data, errors.New("Value is not map ") + } + } + if len(data) == 0 { + return data, fmt.Errorf("vedb_mysql_instance %s not exist ", id) + } + // 接口有问题,实例running后一段时间还是查不到subnet + if subnet, ok := data["SubnetId"]; !ok || subnet == nil || subnet.(string) == "" { + subnetId, ok := resourceData.GetOk("subnet_id") + if !ok { + data["SubnetId"] = "" + } else { + data["SubnetId"] = subnetId.(string) + } + } + return data, err +} + +func (s *VolcengineVedbMysqlInstanceService) RefreshResourceState(resourceData *schema.ResourceData, target []string, timeout time.Duration, id string) *resource.StateChangeConf { + return &resource.StateChangeConf{ + Pending: []string{}, + Delay: 5 * time.Second, + MinTimeout: 1 * time.Second, + Target: target, + Timeout: timeout, + Refresh: func() (result interface{}, state string, err error) { + var ( + d map[string]interface{} + status interface{} + failStates []string + ) + failStates = append(failStates, "CreateFailed", "Unavailable") + if err = resource.Retry(20*time.Minute, func() *resource.RetryError { + d, err = s.ReadResource(resourceData, id) + if err != nil { + if ve.ResourceNotFoundError(err) { + return resource.RetryableError(err) + } else { + return resource.NonRetryableError(err) + } + } + return nil + }); err != nil { + return nil, "", err + } + status, err = ve.ObtainSdkValue("InstanceStatus", d) + if err != nil { + return nil, "", err + } + for _, v := range failStates { + if v == status.(string) { + return nil, "", fmt.Errorf("vedb_mysql_instance status error, status: %s", status.(string)) + } + } + return d, status.(string), err + }, + } +} + +func (s *VolcengineVedbMysqlInstanceService) CreateResource(resourceData *schema.ResourceData, resource *schema.Resource) []ve.Callback { + callback := ve.Callback{ + Call: ve.SdkCall{ + Action: "CreateDBInstance", + ConvertMode: ve.RequestConvertAll, + ContentType: ve.ContentTypeJson, + Convert: map[string]ve.RequestConvert{ + "db_engine_version": { + TargetField: "DBEngineVersion", + }, + "tags": { + TargetField: "Tags", + ConvertType: ve.ConvertJsonObjectArray, + }, + "db_minor_version": { + TargetField: "DBMinorVersion", + }, + "db_time_zone": { + TargetField: "DBTimeZone", + }, + "pre_paid_storage_in_gb": { + TargetField: "PrePaidStorageInGB", + }, + }, + BeforeCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (bool, error) { + var ( + subnets []interface{} + results interface{} + ok bool + ) + // add vpc id + subnetId := d.Get("subnet_id") + req := map[string]interface{}{ + "SubnetIds.1": subnetId, + } + action := "DescribeSubnets" + resp, err := s.Client.UniversalClient.DoCall(getVPCUniversalInfo(action), &req) + if err != nil { + return false, err + } + results, err = ve.ObtainSdkValue("Result.Subnets", *resp) + if err != nil { + return false, err + } + if results == nil { + results = []interface{}{} + } + if subnets, ok = results.([]interface{}); !ok { + return false, errors.New("Result.Subnets is not Slice") + } + if len(subnets) == 0 { + return false, fmt.Errorf("subnet %s not exist", subnetId.(string)) + } + vpcId := subnets[0].(map[string]interface{})["VpcId"] + zoneId := subnets[0].(map[string]interface{})["ZoneId"] + + (*call.SdkParam)["VpcId"] = vpcId + (*call.SdkParam)["ZoneIds"] = zoneId + + return true, nil + }, + ExecuteCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (*map[string]interface{}, error) { + logger.Debug(logger.RespFormat, call.Action, call.SdkParam) + resp, err := s.Client.UniversalClient.DoCall(getUniversalInfo(call.Action), call.SdkParam) + logger.Debug(logger.RespFormat, call.Action, resp, err) + return resp, err + }, + AfterCall: func(d *schema.ResourceData, client *ve.SdkClient, resp *map[string]interface{}, call ve.SdkCall) error { + id, _ := ve.ObtainSdkValue("Result.InstanceId", *resp) + d.SetId(id.(string)) + return nil + }, + Refresh: &ve.StateRefresh{ + Target: []string{"Running"}, + Timeout: resourceData.Timeout(schema.TimeoutCreate), + }, + }, + } + return []ve.Callback{callback} +} + +func (VolcengineVedbMysqlInstanceService) WithResourceResponseHandlers(d map[string]interface{}) []ve.ResourceResponseHandler { + handler := func() (map[string]interface{}, map[string]ve.ResponseConvert, error) { + return d, map[string]ve.ResponseConvert{ + "DBEngineVersion": { + TargetField: "db_engine_version", + }, + "DBMinorVersion": { + TargetField: "db_minor_version", + }, + "DBTimeZone": { + TargetField: "db_time_zone", + }, + "PrePaidStorageInGB": { + TargetField: "pre_paid_storage_in_gb", + }, + }, nil + } + return []ve.ResourceResponseHandler{handler} +} + +func (s *VolcengineVedbMysqlInstanceService) ModifyResource(resourceData *schema.ResourceData, resource *schema.Resource) []ve.Callback { + var callbacks []ve.Callback + if resourceData.HasChanges("instance_name") { + nameCallback := ve.Callback{ + Call: ve.SdkCall{ + Action: "ModifyDBInstanceName", + ConvertMode: ve.RequestConvertInConvert, + ContentType: ve.ContentTypeJson, + Convert: map[string]ve.RequestConvert{ + "instance_name": { + TargetField: "InstanceNewName", + }, + }, + BeforeCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (bool, error) { + (*call.SdkParam)["InstanceId"] = d.Id() + return true, nil + }, + ExecuteCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (*map[string]interface{}, error) { + logger.Debug(logger.ReqFormat, call.Action, call.SdkParam) + resp, err := s.Client.UniversalClient.DoCall(getUniversalInfo(call.Action), call.SdkParam) + logger.Debug(logger.RespFormat, call.Action, resp, err) + return resp, err + }, + Refresh: &ve.StateRefresh{ + Target: []string{"Running"}, + Timeout: resourceData.Timeout(schema.TimeoutCreate), + }, + }, + } + callbacks = append(callbacks, nameCallback) + } + + if resourceData.HasChanges("node_spec", "node_number", "pre_paid_storage_in_gb") { + specCallback := ve.Callback{ + Call: ve.SdkCall{ + Action: "ModifyDBInstanceSpec", + ConvertMode: ve.RequestConvertInConvert, + ContentType: ve.ContentTypeJson, + Convert: map[string]ve.RequestConvert{ + "node_spec": { + TargetField: "NodeSpec", + ForceGet: true, + }, + "node_number": { + TargetField: "NodeNumber", + ForceGet: true, + }, + "pre_paid_storage_in_gb": { + TargetField: "PrePaidStorageInGB", + }, + }, + BeforeCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (bool, error) { + (*call.SdkParam)["InstanceId"] = d.Id() + return true, nil + }, + ExecuteCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (*map[string]interface{}, error) { + logger.Debug(logger.ReqFormat, call.Action, call.SdkParam) + resp, err := s.Client.UniversalClient.DoCall(getUniversalInfo(call.Action), call.SdkParam) + logger.Debug(logger.RespFormat, call.Action, resp, err) + return resp, err + }, + Refresh: &ve.StateRefresh{ + Target: []string{"Running"}, + Timeout: resourceData.Timeout(schema.TimeoutCreate), + }, + }, + } + callbacks = append(callbacks, specCallback) + } + + if resourceData.HasChanges("charge_type", "storage_charge_type", "auto_renew", + "period_unit", "period") { + chargeCallback := ve.Callback{ + Call: ve.SdkCall{ + Action: "ModifyDBInstanceChargeType", + ConvertMode: ve.RequestConvertInConvert, + ContentType: ve.ContentTypeJson, + Convert: map[string]ve.RequestConvert{ + "charge_type": { + TargetField: "ChargeType", + ForceGet: true, + }, + "storage_charge_type": { + TargetField: "StorageChargeType", + }, + "auto_renew": { + TargetField: "AutoRenew", + ForceGet: true, + }, + "period_unit": { + TargetField: "PeriodUnit", + ForceGet: true, + }, + "period": { + TargetField: "Period", + ForceGet: true, + }, + }, + BeforeCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (bool, error) { + (*call.SdkParam)["InstanceId"] = d.Id() + // 不支持包年包月转按量计费,让API报错吧,不管了 + return true, nil + }, + ExecuteCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (*map[string]interface{}, error) { + logger.Debug(logger.ReqFormat, call.Action, call.SdkParam) + resp, err := s.Client.UniversalClient.DoCall(getUniversalInfo(call.Action), call.SdkParam) + logger.Debug(logger.RespFormat, call.Action, resp, err) + return resp, err + }, + Refresh: &ve.StateRefresh{ + Target: []string{"Running"}, + Timeout: resourceData.Timeout(schema.TimeoutCreate), + }, + }, + } + callbacks = append(callbacks, chargeCallback) + } + + // tag + callbacks = s.setResourceTags(resourceData, callbacks) + return callbacks +} + +func (s *VolcengineVedbMysqlInstanceService) RemoveResource(resourceData *schema.ResourceData, r *schema.Resource) []ve.Callback { + callback := ve.Callback{ + Call: ve.SdkCall{ + Action: "DeleteDBInstance", + ConvertMode: ve.RequestConvertIgnore, + ContentType: ve.ContentTypeJson, + SdkParam: &map[string]interface{}{ + "InstanceId": resourceData.Id(), + }, + ExecuteCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (*map[string]interface{}, error) { + logger.Debug(logger.RespFormat, call.Action, call.SdkParam) + return s.Client.UniversalClient.DoCall(getUniversalInfo(call.Action), call.SdkParam) + }, + AfterCall: func(d *schema.ResourceData, client *ve.SdkClient, resp *map[string]interface{}, call ve.SdkCall) error { + return ve.CheckResourceUtilRemoved(d, s.ReadResource, 10*time.Minute) + }, + CallError: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall, baseErr error) error { + //出现错误后重试 + return resource.Retry(15*time.Minute, func() *resource.RetryError { + _, callErr := s.ReadResource(d, "") + if callErr != nil { + if ve.ResourceNotFoundError(callErr) { + return nil + } else { + return resource.NonRetryableError(fmt.Errorf("error on reading vedb mysql instance on delete %q, %w", d.Id(), callErr)) + } + } + _, callErr = call.ExecuteCall(d, client, call) + if callErr == nil { + return nil + } + return resource.RetryableError(callErr) + }) + }, + }, + } + return []ve.Callback{callback} +} + +func (s *VolcengineVedbMysqlInstanceService) DatasourceResources(*schema.ResourceData, *schema.Resource) ve.DataSourceInfo { + return ve.DataSourceInfo{ + RequestConverts: map[string]ve.RequestConvert{ + "db_engine_version": { + TargetField: "DBEngineVersion", + }, + "tags": { + TargetField: "TagFilters", + ConvertType: ve.ConvertJsonObjectArray, + }, + }, + NameField: "InstanceName", + IdField: "InstanceId", + CollectField: "instances", + ContentType: ve.ContentTypeJson, + ResponseConverts: map[string]ve.ResponseConvert{ + "InstanceId": { + TargetField: "id", + KeepDefault: true, + }, + "DBEngineVersion": { + TargetField: "db_engine_version", + }, + "PrePaidStorageInGB": { + TargetField: "pre_paid_storage_in_gb", + }, + "StorageUsedGiB": { + TargetField: "storage_used_gib", + }, + "vCPU": { + TargetField: "v_cpu", + }, + }, + } +} + +func (s *VolcengineVedbMysqlInstanceService) ReadResourceId(id string) string { + return id +} + +func getVPCUniversalInfo(actionName string) ve.UniversalInfo { + return ve.UniversalInfo{ + ServiceName: "vpc", + Version: "2020-04-01", + HttpMethod: ve.GET, + Action: actionName, + } +} + +func getUniversalInfo(actionName string) ve.UniversalInfo { + return ve.UniversalInfo{ + ServiceName: "vedbm", + Version: "2022-01-01", + HttpMethod: ve.POST, + ContentType: ve.ApplicationJSON, + Action: actionName, + } +} + +func (s *VolcengineVedbMysqlInstanceService) ProjectTrn() *ve.ProjectTrn { + return &ve.ProjectTrn{ + ServiceName: "vedbm", + ResourceType: "instance", + ProjectResponseField: "ProjectName", + ProjectSchemaField: "project_name", + } +} + +func (s *VolcengineVedbMysqlInstanceService) UnsubscribeInfo(resourceData *schema.ResourceData, resource *schema.Resource) (*ve.UnsubscribeInfo, error) { + info := ve.UnsubscribeInfo{ + InstanceId: s.ReadResourceId(resourceData.Id()), + } + if resourceData.Get("charge_type").(string) == "PrePaid" { + info.NeedUnsubscribe = true + info.Products = []string{"veDB for MySQL"} + } + return &info, nil +} + +func (s *VolcengineVedbMysqlInstanceService) setResourceTags(resourceData *schema.ResourceData, callbacks []ve.Callback) []ve.Callback { + addedTags, removedTags, _, _ := ve.GetSetDifference("tags", resourceData, ve.TagsHash, false) + + removeCallback := ve.Callback{ + Call: ve.SdkCall{ + Action: "RemoveTagsFromResource", + ConvertMode: ve.RequestConvertIgnore, + BeforeCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (bool, error) { + if removedTags != nil && len(removedTags.List()) > 0 { + (*call.SdkParam)["InstanceIds"] = []string{resourceData.Id()} + (*call.SdkParam)["TagKeys"] = make([]string, 0) + for _, tag := range removedTags.List() { + (*call.SdkParam)["TagKeys"] = append((*call.SdkParam)["TagKeys"].([]string), tag.(map[string]interface{})["key"].(string)) + } + return true, nil + } + return false, nil + }, + ExecuteCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (*map[string]interface{}, error) { + logger.Debug(logger.ReqFormat, call.Action, call.SdkParam) + return s.Client.UniversalClient.DoCall(getUniversalInfo(call.Action), call.SdkParam) + }, + }, + } + callbacks = append(callbacks, removeCallback) + + addCallback := ve.Callback{ + Call: ve.SdkCall{ + Action: "AddTagsToResource", + ConvertMode: ve.RequestConvertIgnore, + BeforeCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (bool, error) { + if addedTags != nil && len(addedTags.List()) > 0 { + (*call.SdkParam)["InstanceIds"] = []string{resourceData.Id()} + (*call.SdkParam)["Tags"] = make([]map[string]interface{}, 0) + for _, tag := range addedTags.List() { + (*call.SdkParam)["Tags"] = append((*call.SdkParam)["Tags"].([]map[string]interface{}), tag.(map[string]interface{})) + } + return true, nil + } + return false, nil + }, + ExecuteCall: func(d *schema.ResourceData, client *ve.SdkClient, call ve.SdkCall) (*map[string]interface{}, error) { + logger.Debug(logger.ReqFormat, call.Action, call.SdkParam) + return s.Client.UniversalClient.DoCall(getUniversalInfo(call.Action), call.SdkParam) + }, + }, + } + callbacks = append(callbacks, addCallback) + + return callbacks +} diff --git a/website/docs/d/redis_instances.html.markdown b/website/docs/d/redis_instances.html.markdown index eef932f9..b28112f6 100644 --- a/website/docs/d/redis_instances.html.markdown +++ b/website/docs/d/redis_instances.html.markdown @@ -128,6 +128,8 @@ disabled: Single availability zone deployment scheme. * `address` - The connection address. * `eip_id` - The EIP ID bound to the instance's public network address. * `port` - The connection port. + * `vip_v6` - The ipv6 address of the connection address. + * `vip` - The ipv4 address of the connection address. * `vpc_auth_mode` - Whether to enable password-free access when connecting to an instance through a private network. * `vpc_id` - The vpc ID of the redis instance. * `zone_ids` - The list of zone ID which the redis instance belongs. diff --git a/website/docs/d/tls_projects.html.markdown b/website/docs/d/tls_projects.html.markdown index 45aaaf94..eb14563a 100644 --- a/website/docs/d/tls_projects.html.markdown +++ b/website/docs/d/tls_projects.html.markdown @@ -11,7 +11,7 @@ Use this data source to query detailed information of tls projects ## Example Usage ```hcl data "volcengine_tls_projects" "default" { - project_id = "e020c978-4f05-40e1-9167-0113d3ef****" + #project_id = "e020c978-4f05-40e1-9167-0113d3ef****" } ``` ## Argument Reference diff --git a/website/docs/d/vedb_mysql_accounts.html.markdown b/website/docs/d/vedb_mysql_accounts.html.markdown new file mode 100644 index 00000000..bab02f29 --- /dev/null +++ b/website/docs/d/vedb_mysql_accounts.html.markdown @@ -0,0 +1,89 @@ +--- +subcategory: "VEDB_MYSQL" +layout: "volcengine" +page_title: "Volcengine: volcengine_vedb_mysql_accounts" +sidebar_current: "docs-volcengine-datasource-vedb_mysql_accounts" +description: |- + Use this data source to query detailed information of vedb mysql accounts +--- +# volcengine_vedb_mysql_accounts +Use this data source to query detailed information of vedb mysql accounts +## Example Usage +```hcl +data "volcengine_zones" "foo" { +} + +resource "volcengine_vpc" "foo" { + vpc_name = "acc-test-vpc" + cidr_block = "172.16.0.0/16" +} + +resource "volcengine_subnet" "foo" { + subnet_name = "acc-test-subnet" + cidr_block = "172.16.0.0/24" + zone_id = data.volcengine_zones.foo.zones[2].id + vpc_id = volcengine_vpc.foo.id +} + + +resource "volcengine_vedb_mysql_instance" "foo" { + charge_type = "PostPaid" + storage_charge_type = "PostPaid" + db_engine_version = "MySQL_8_0" + db_minor_version = "3.0" + node_number = 2 + node_spec = "vedb.mysql.x4.large" + subnet_id = volcengine_subnet.foo.id + instance_name = "tf-test" + project_name = "testA" + tags { + key = "tftest" + value = "tftest" + } + tags { + key = "tftest2" + value = "tftest2" + } +} + +resource "volcengine_vedb_mysql_database" "foo" { + db_name = "tf-table" + instance_id = volcengine_vedb_mysql_instance.foo.id +} + +resource "volcengine_vedb_mysql_account" "foo" { + account_name = "tftest" + account_password = "93f0cb0614Aab12" + account_type = "Normal" + instance_id = volcengine_vedb_mysql_instance.foo.id + account_privileges { + db_name = volcengine_vedb_mysql_database.foo.db_name + account_privilege = "Custom" + account_privilege_detail = "SELECT,INSERT,DELETE" + } +} + +data "volcengine_vedb_mysql_accounts" "foo" { + account_name = volcengine_vedb_mysql_account.foo.account_name + instance_id = volcengine_vedb_mysql_instance.foo.id +} +``` +## Argument Reference +The following arguments are supported: +* `instance_id` - (Required) The id of the veDB Mysql instance. +* `account_name` - (Optional) The name of the database account. This field supports fuzzy query. +* `name_regex` - (Optional) A Name Regex of Resource. +* `output_file` - (Optional) File name where to save data source results. + +## Attributes Reference +In addition to all arguments above, the following attributes are exported: +* `accounts` - The collection of query. + * `account_name` - The name of the database account. + * `account_privileges` - The privilege detail list of RDS mysql instance account. + * `account_privilege_detail` - The privilege detail of the account. + * `account_privilege` - The privilege type of the account. + * `db_name` - The name of database. + * `account_type` - The type of the database account. +* `total_count` - The total count of query. + + diff --git a/website/docs/d/vedb_mysql_allowlists.html.markdown b/website/docs/d/vedb_mysql_allowlists.html.markdown new file mode 100644 index 00000000..b5abc74b --- /dev/null +++ b/website/docs/d/vedb_mysql_allowlists.html.markdown @@ -0,0 +1,88 @@ +--- +subcategory: "VEDB_MYSQL" +layout: "volcengine" +page_title: "Volcengine: volcengine_vedb_mysql_allowlists" +sidebar_current: "docs-volcengine-datasource-vedb_mysql_allowlists" +description: |- + Use this data source to query detailed information of vedb mysql allowlists +--- +# volcengine_vedb_mysql_allowlists +Use this data source to query detailed information of vedb mysql allowlists +## Example Usage +```hcl +resource "volcengine_vedb_mysql_allowlist" "foo" { + allow_list_name = "acc-test-allowlist" + allow_list_desc = "acc-test" + allow_list_type = "IPv4" + allow_list = ["192.168.0.0/24", "192.168.1.0/24", "192.168.2.0/24"] +} + +data "volcengine_zones" "foo" { +} + +resource "volcengine_vpc" "foo" { + vpc_name = "acc-test-vpc" + cidr_block = "172.16.0.0/16" +} + +resource "volcengine_subnet" "foo" { + subnet_name = "acc-test-subnet" + cidr_block = "172.16.0.0/24" + zone_id = data.volcengine_zones.foo.zones[2].id + vpc_id = volcengine_vpc.foo.id +} + + +resource "volcengine_vedb_mysql_instance" "foo" { + charge_type = "PostPaid" + storage_charge_type = "PostPaid" + db_engine_version = "MySQL_8_0" + db_minor_version = "3.0" + node_number = 2 + node_spec = "vedb.mysql.x4.large" + subnet_id = volcengine_subnet.foo.id + instance_name = "tf-test" + project_name = "testA" + tags { + key = "tftest" + value = "tftest" + } + tags { + key = "tftest2" + value = "tftest2" + } +} + +resource "volcengine_vedb_mysql_allowlist_associate" "foo" { + allow_list_id = volcengine_vedb_mysql_allowlist.foo.id + instance_id = volcengine_vedb_mysql_instance.foo.id +} + +data "volcengine_vedb_mysql_allowlists" "foo" { + instance_id = volcengine_vedb_mysql_instance.foo.id +} +``` +## Argument Reference +The following arguments are supported: +* `region_id` - (Required) The region of the allow lists. +* `instance_id` - (Optional) Instance ID. When an InstanceId is specified, the DescribeAllowLists interface will return the whitelist bound to the specified instance. +* `name_regex` - (Optional) A Name Regex of Resource. +* `output_file` - (Optional) File name where to save data source results. + +## Attributes Reference +In addition to all arguments above, the following attributes are exported: +* `allow_lists` - The collection of query. + * `allow_list_desc` - The description of the allow list. + * `allow_list_id` - The id of the allow list. + * `allow_list_ip_num` - The total number of IP addresses (or address ranges) in the whitelist. + * `allow_list_name` - The name of the allow list. + * `allow_list_type` - The type of the allow list. + * `allow_list` - The IP address or a range of IP addresses in CIDR format. + * `associated_instance_num` - The total number of instances bound under the whitelist. + * `associated_instances` - The list of instances. + * `instance_id` - The id of the instance. + * `instance_name` - The name of the instance. + * `vpc` - The id of the vpc. +* `total_count` - The total count of query. + + diff --git a/website/docs/d/vedb_mysql_backups.html.markdown b/website/docs/d/vedb_mysql_backups.html.markdown new file mode 100644 index 00000000..52c05323 --- /dev/null +++ b/website/docs/d/vedb_mysql_backups.html.markdown @@ -0,0 +1,100 @@ +--- +subcategory: "VEDB_MYSQL" +layout: "volcengine" +page_title: "Volcengine: volcengine_vedb_mysql_backups" +sidebar_current: "docs-volcengine-datasource-vedb_mysql_backups" +description: |- + Use this data source to query detailed information of vedb mysql backups +--- +# volcengine_vedb_mysql_backups +Use this data source to query detailed information of vedb mysql backups +## Example Usage +```hcl +data "volcengine_zones" "foo" { +} + +resource "volcengine_vpc" "foo" { + vpc_name = "acc-test-vpc" + cidr_block = "172.16.0.0/16" +} + +resource "volcengine_subnet" "foo" { + subnet_name = "acc-test-subnet" + cidr_block = "172.16.0.0/24" + zone_id = data.volcengine_zones.foo.zones[2].id + vpc_id = volcengine_vpc.foo.id +} + + +resource "volcengine_vedb_mysql_instance" "foo" { + charge_type = "PostPaid" + storage_charge_type = "PostPaid" + db_engine_version = "MySQL_8_0" + db_minor_version = "3.0" + node_number = 2 + node_spec = "vedb.mysql.x4.large" + subnet_id = volcengine_subnet.foo.id + instance_name = "tf-test" + project_name = "testA" + tags { + key = "tftest" + value = "tftest" + } + tags { + key = "tftest2" + value = "tftest2" + } +} + +resource "volcengine_vedb_mysql_backup" "foo" { + instance_id = volcengine_vedb_mysql_instance.foo.id + backup_policy { + backup_time = "18:00Z-20:00Z" + full_backup_period = "Monday,Tuesday,Wednesday" + backup_retention_period = 8 + } +} + +data "volcengine_vedb_mysql_backups" "foo" { + instance_id = volcengine_vedb_mysql_instance.foo.id +} +``` +## Argument Reference +The following arguments are supported: +* `instance_id` - (Required) The id of the instance. +* `backup_end_time` - (Optional) The end time of the backup. +* `backup_method` - (Optional) Backup method. Currently, only physical backup is supported. The value is Physical. +* `backup_start_time` - (Optional) The start time of the backup. +* `backup_status` - (Optional) The status of the backup. +* `backup_type` - (Optional) The type of the backup. +* `output_file` - (Optional) File name where to save data source results. + +## Attributes Reference +In addition to all arguments above, the following attributes are exported: +* `backups` - The collection of query. + * `backup_end_time` - The end time of the backup. + * `backup_file_size` - The size of the backup file. + * `backup_id` - The id of the backup. + * `backup_method` - The name of the backup method. + * `backup_policy` - Data backup strategy for instances. + * `backup_retention_period` - Data backup retention period, value: 7 to 30 days. + * `backup_time` - The time for executing the backup task. The interval window is two hours. Format: HH:mmZ-HH:mmZ (UTC time). + * `continue_backup` - Whether to enable continuous backup. The value is fixed as true. + * `full_backup_period` - Full backup period. Multiple values are separated by English commas (,). Values: +Monday: Monday. +Tuesday: Tuesday. +Wednesday: Wednesday. +Thursday: Thursday. +Friday: Friday. +Saturday: Saturday. +Sunday: Sunday. + * `instance_id` - The id of the instance. + * `backup_start_time` - The start time of the backup. + * `backup_status` - The status of the backup. + * `backup_type` - The type of the backup. + * `consistent_time` - The time point of consistent backup, in the format: yyyy-MM-ddTHH:mm:ssZ (UTC time). + * `create_type` - The type of the backup create. + * `id` - The id of the backup. +* `total_count` - The total count of query. + + diff --git a/website/docs/d/vedb_mysql_databases.html.markdown b/website/docs/d/vedb_mysql_databases.html.markdown new file mode 100644 index 00000000..b9478753 --- /dev/null +++ b/website/docs/d/vedb_mysql_databases.html.markdown @@ -0,0 +1,76 @@ +--- +subcategory: "VEDB_MYSQL" +layout: "volcengine" +page_title: "Volcengine: volcengine_vedb_mysql_databases" +sidebar_current: "docs-volcengine-datasource-vedb_mysql_databases" +description: |- + Use this data source to query detailed information of vedb mysql databases +--- +# volcengine_vedb_mysql_databases +Use this data source to query detailed information of vedb mysql databases +## Example Usage +```hcl +data "volcengine_zones" "foo" { +} + +resource "volcengine_vpc" "foo" { + vpc_name = "acc-test-vpc" + cidr_block = "172.16.0.0/16" +} + +resource "volcengine_subnet" "foo" { + subnet_name = "acc-test-subnet" + cidr_block = "172.16.0.0/24" + zone_id = data.volcengine_zones.foo.zones[2].id + vpc_id = volcengine_vpc.foo.id +} + + +resource "volcengine_vedb_mysql_instance" "foo" { + charge_type = "PostPaid" + storage_charge_type = "PostPaid" + db_engine_version = "MySQL_8_0" + db_minor_version = "3.0" + node_number = 2 + node_spec = "vedb.mysql.x4.large" + subnet_id = volcengine_subnet.foo.id + instance_name = "tf-test" + project_name = "testA" + tags { + key = "tftest" + value = "tftest" + } + tags { + key = "tftest2" + value = "tftest2" + } +} + +resource "volcengine_vedb_mysql_database" "foo" { + db_name = "tf-table" + instance_id = volcengine_vedb_mysql_instance.foo.id +} + +data "volcengine_vedb_mysql_databases" "foo" { + db_name = volcengine_vedb_mysql_database.foo.db_name + instance_id = volcengine_vedb_mysql_instance.foo.id +} +``` +## Argument Reference +The following arguments are supported: +* `instance_id` - (Required) The instance id. +* `db_name` - (Optional) Database name. +* `name_regex` - (Optional) A Name Regex of Resource. +* `output_file` - (Optional) File name where to save data source results. + +## Attributes Reference +In addition to all arguments above, the following attributes are exported: +* `databases` - The collection of query. + * `character_set_name` - Database character set: utf8mb4 (default), utf8, latin1, ascii. + * `db_name` - The name of the database. Naming rules: + Unique name. Start with a lowercase letter and end with a letter or number. The length is within 2 to 64 characters. + Consist of lowercase letters, numbers, underscores (_), or hyphens (-). + The name cannot contain certain reserved words. +* `total_count` - The total count of query. + + diff --git a/website/docs/d/vedb_mysql_endpoints.html.markdown b/website/docs/d/vedb_mysql_endpoints.html.markdown new file mode 100644 index 00000000..2139f3c7 --- /dev/null +++ b/website/docs/d/vedb_mysql_endpoints.html.markdown @@ -0,0 +1,137 @@ +--- +subcategory: "VEDB_MYSQL" +layout: "volcengine" +page_title: "Volcengine: volcengine_vedb_mysql_endpoints" +sidebar_current: "docs-volcengine-datasource-vedb_mysql_endpoints" +description: |- + Use this data source to query detailed information of vedb mysql endpoints +--- +# volcengine_vedb_mysql_endpoints +Use this data source to query detailed information of vedb mysql endpoints +## Example Usage +```hcl +data "volcengine_zones" "foo" { +} + +resource "volcengine_vpc" "foo" { + vpc_name = "acc-test-vpc" + cidr_block = "172.16.0.0/16" +} + +resource "volcengine_subnet" "foo" { + subnet_name = "acc-test-subnet" + cidr_block = "172.16.0.0/24" + zone_id = data.volcengine_zones.foo.zones[2].id + vpc_id = volcengine_vpc.foo.id +} + + +resource "volcengine_vedb_mysql_instance" "foo" { + charge_type = "PostPaid" + storage_charge_type = "PostPaid" + db_engine_version = "MySQL_8_0" + db_minor_version = "3.0" + node_number = 2 + node_spec = "vedb.mysql.x4.large" + subnet_id = volcengine_subnet.foo.id + instance_name = "tf-test" + project_name = "testA" + tags { + key = "tftest" + value = "tftest" + } + tags { + key = "tftest2" + value = "tftest2" + } +} +data "volcengine_vedb_mysql_instances" "foo" { + instance_id = volcengine_vedb_mysql_instance.foo.id +} + +resource "volcengine_vedb_mysql_endpoint" "foo" { + endpoint_type = "Custom" + instance_id = volcengine_vedb_mysql_instance.foo.id + node_ids = [data.volcengine_vedb_mysql_instances.foo.instances[0].nodes[0].node_id, data.volcengine_vedb_mysql_instances.foo.instances[0].nodes[1].node_id] + read_write_mode = "ReadWrite" + endpoint_name = "tf-test" + description = "tf test" + master_accept_read_requests = true + distributed_transaction = true + consist_level = "Session" + consist_timeout = 100000 + consist_timeout_action = "ReadMaster" +} + +data "volcengine_vedb_mysql_endpoints" "foo" { + endpoint_id = volcengine_vedb_mysql_endpoint.foo.endpoint_id + instance_id = volcengine_vedb_mysql_instance.foo.id +} +``` +## Argument Reference +The following arguments are supported: +* `instance_id` - (Required) The id of the instance. +* `endpoint_id` - (Optional) The id of the endpoint. +* `name_regex` - (Optional) A Name Regex of Resource. +* `output_file` - (Optional) File name where to save data source results. + +## Attributes Reference +In addition to all arguments above, the following attributes are exported: +* `endpoints` - The collection of query. + * `addresses` - The address information. + * `dns_visibility` - Parsing method. Currently, the return value can only be false (Volcengine private network parsing). + * `domain` - Instance intranet access domain name. + * `eip_id` - The EIP id. + * `ip_address` - IP address. + * `network_type` - Network type: +Private: Private network VPC. +Public: Public network access. + * `port` - Instance intranet access port. + * `subnet_id` - Subnet ID. The subnet must belong to the selected availability zone. +Description + A subnet is an IP address block within a private network. All cloud resources in a private network must be deployed within a subnet. The subnet assigns private IP addresses to cloud resources. + * `auto_add_new_nodes` - Set whether newly created read-only nodes will automatically join this connection endpoint. Values: +true: Automatically join. +false: Do not automatically join (default). + * `consist_level` - Consistency level. For detailed introduction of consistency level, please refer to consistency level. Value range: +Eventual: eventual consistency. +Session: session consistency. +Global: global consistency. +Description +When the value of ReadWriteMode is ReadWrite, the selectable consistency levels are Eventual, Session (default), and Global. +When the value of ReadWriteMode is ReadOnly, the consistency level is Eventual by default and cannot be changed. + * `consist_timeout_action` - Timeout policy after data synchronization timeout of read-only nodes supports the following two policies: +ReturnError: Return SQL error (wait replication complete timeout, please retry). +ReadMaster: Send a request to the master node (default). +Description + This parameter takes effect only when the value of ConsistLevel is Global or Session. + * `consist_timeout` - When there is a large delay, the timeout period for read-only nodes to synchronize the latest data, in us. The value range is from 1us to 100000000us, and the default value is 10000us. +Explanation + This parameter takes effect only when the value of ConsistLevel is Global or Session. + * `description` - Description information for connecting endpoint. The length cannot exceed 200 characters. + * `distributed_transaction` - Set whether to enable transaction splitting. For detailed introduction to transaction splitting, please refer to transaction splitting. Value range: +true: Enabled (default). +false: Disabled. +Description +Only when the value of ReadWriteMode is ReadWrite, is enabling transaction splitting supported. + * `endpoint_id` - The id of the endpoint. + * `endpoint_name` - Connect the endpoint name. The setting rules are as follows: + It cannot start with a number or a hyphen (-). + It can only contain Chinese characters, letters, numbers, underscores (_), and hyphens (-). + The length is 1 to 64 characters. + * `endpoint_type` - Connect terminal type. The value is fixed as Custom, indicating a custom terminal. + * `id` - The id of the endpoint. + * `master_accept_read_requests` - The master node accepts read requests. Value range: +true: (default) After enabling the master node to accept read functions, non-transactional read requests will be sent to the master node or read-only nodes in a load-balanced mode according to the number of active requests. +false: After disabling the master node from accepting read requests, at this time, the master node only accepts transactional read requests, and non-transactional read requests will not be sent to the master node. +Description +Only when the value of ReadWriteMode is ReadWrite, enabling the master node to accept reads is supported. + * `node_ids` - Connect the node IDs associated with the endpoint.The filling rules are as follows: +When the value of ReadWriteMode is ReadWrite, at least two nodes must be passed in, and the master node must be passed in. +When the value of ReadWriteMode is ReadOnly, one or more read-only nodes can be passed in. + * `read_write_mode` - Endpoint read-write mode. Values: + ReadWrite: Read and write terminal. + ReadOnly: Read-only terminal (default). +* `total_count` - The total count of query. + + diff --git a/website/docs/d/vedb_mysql_instances.html.markdown b/website/docs/d/vedb_mysql_instances.html.markdown new file mode 100644 index 00000000..841ef5e1 --- /dev/null +++ b/website/docs/d/vedb_mysql_instances.html.markdown @@ -0,0 +1,125 @@ +--- +subcategory: "VEDB_MYSQL" +layout: "volcengine" +page_title: "Volcengine: volcengine_vedb_mysql_instances" +sidebar_current: "docs-volcengine-datasource-vedb_mysql_instances" +description: |- + Use this data source to query detailed information of vedb mysql instances +--- +# volcengine_vedb_mysql_instances +Use this data source to query detailed information of vedb mysql instances +## Example Usage +```hcl +data "volcengine_zones" "foo" { +} + +resource "volcengine_vpc" "foo" { + vpc_name = "acc-test-vpc" + cidr_block = "172.16.0.0/16" +} + +resource "volcengine_subnet" "foo" { + subnet_name = "acc-test-subnet" + cidr_block = "172.16.0.0/24" + zone_id = data.volcengine_zones.foo.zones[2].id + vpc_id = volcengine_vpc.foo.id +} + + +resource "volcengine_vedb_mysql_instance" "foo" { + charge_type = "PostPaid" + storage_charge_type = "PostPaid" + db_engine_version = "MySQL_8_0" + db_minor_version = "3.0" + node_number = 2 + node_spec = "vedb.mysql.x4.large" + subnet_id = volcengine_subnet.foo.id + instance_name = "tf-test" + project_name = "testA" + tags { + key = "tftest" + value = "tftest" + } + tags { + key = "tftest2" + value = "tftest2" + } +} + +data "volcengine_vedb_mysql_instances" "foo" { + instance_id = volcengine_vedb_mysql_instance.foo.id +} +``` +## Argument Reference +The following arguments are supported: +* `charge_type` - (Optional) The charge type of the veDB Mysql instance. +* `create_time_end` - (Optional) The end time of creating veDB Mysql instance. +* `create_time_start` - (Optional) The start time of creating veDB Mysql instance. +* `db_engine_version` - (Optional) The version of the veDB Mysql instance. +* `instance_id` - (Optional) The id of the veDB Mysql instance. +* `instance_name` - (Optional) The name of the veDB Mysql instance. +* `instance_status` - (Optional) The status of the veDB Mysql instance. +* `name_regex` - (Optional) A Name Regex of veDB mysql instance. +* `output_file` - (Optional) File name where to save data source results. +* `project_name` - (Optional) The project name of the veDB Mysql instance. +* `tags` - (Optional) Tags. +* `zone_id` - (Optional) The available zone of the veDB Mysql instance. + +The `tags` object supports the following: + +* `key` - (Required) The Key of Tags. +* `value` - (Required) The Value of Tags. + +## Attributes Reference +In addition to all arguments above, the following attributes are exported: +* `instances` - The collection of query. + * `auto_renew` - Whether auto-renewal is enabled in the prepaid scenario. Values: +true: Auto-renewal is enabled. +false: Auto-renewal is not enabled. + * `charge_end_time` - The billing expiration time in the prepaid scenario, in the format: yyyy-MM-ddTHH:mm:ssZ (UTC time). + * `charge_start_time` - The time when billing starts. Format: yyyy-MM-ddTHH:mm:ssZ (UTC time). + * `charge_status` - Payment status: +Normal: Normal. +Overdue: In arrears. +Shutdown: Shut down. + * `charge_type` - Calculate the billing type. Values: +PostPaid: Pay-as-you-go (postpaid). +PrePaid: Monthly/yearly subscription (prepaid). + * `create_time` - The create time of the veDB Mysql instance. + * `db_engine_version` - The engine version of the veDB Mysql instance. + * `id` - The ID of the veDB Mysql instance. + * `instance_id` - The ID of the veDB Mysql instance. + * `instance_name` - The name of the veDB Mysql instance. + * `instance_status` - The status of the veDB Mysql instance. + * `lower_case_table_names` - Whether the table name is case sensitive, the default value is 1. +Ranges: +0: Table names are stored as fixed and table names are case-sensitive. +1: Table names will be stored in lowercase and table names are not case sensitive. + * `nodes` - Detailed information of instance nodes. + * `memory` - Memory size, in GiB. + * `node_id` - The id of the node. + * `node_spec` - Node specification of an instance. + * `node_type` - Node type. Values: +Primary: Primary node. +ReadOnly: Read-only node. + * `v_cpu` - CPU size. For example, when the value is 1, it means the CPU size is 1U. + * `zone_id` - The zone id. + * `overdue_reclaim_time` - Expected release time when shut down due to arrears. Format: yyyy-MM-ddTHH:mm:ssZ (UTC time). + * `overdue_time` - Overdue shutdown time. Format: yyyy-MM-ddTHH:mm:ssZ (UTC time). + * `pre_paid_storage_in_gb` - Total storage capacity in GiB for prepaid services. + * `project_name` - The project name of the veDB Mysql instance. + * `region_id` - The region id. + * `storage_charge_type` - Storage billing type. Values: +PostPaid: Pay-as-you-go (postpaid). +PrePaid: Monthly/yearly subscription (prepaid). + * `storage_used_gib` - Used storage size, unit: GiB. + * `subnet_id` - The subnet ID of the veDB Mysql instance. + * `tags` - Tags. + * `key` - The Key of Tags. + * `value` - The Value of Tags. + * `time_zone` - Time zone. + * `vpc_id` - The vpc ID of the veDB Mysql instance. + * `zone_ids` - The available zone of the veDB Mysql instance. +* `total_count` - The total count of query. + + diff --git a/website/docs/r/vedb_mysql_account.html.markdown b/website/docs/r/vedb_mysql_account.html.markdown new file mode 100644 index 00000000..1d912545 --- /dev/null +++ b/website/docs/r/vedb_mysql_account.html.markdown @@ -0,0 +1,107 @@ +--- +subcategory: "VEDB_MYSQL" +layout: "volcengine" +page_title: "Volcengine: volcengine_vedb_mysql_account" +sidebar_current: "docs-volcengine-resource-vedb_mysql_account" +description: |- + Provides a resource to manage vedb mysql account +--- +# volcengine_vedb_mysql_account +Provides a resource to manage vedb mysql account +## Example Usage +```hcl +data "volcengine_zones" "foo" { +} + +resource "volcengine_vpc" "foo" { + vpc_name = "acc-test-vpc" + cidr_block = "172.16.0.0/16" +} + +resource "volcengine_subnet" "foo" { + subnet_name = "acc-test-subnet" + cidr_block = "172.16.0.0/24" + zone_id = data.volcengine_zones.foo.zones[2].id + vpc_id = volcengine_vpc.foo.id +} + + +resource "volcengine_vedb_mysql_instance" "foo" { + charge_type = "PostPaid" + storage_charge_type = "PostPaid" + db_engine_version = "MySQL_8_0" + db_minor_version = "3.0" + node_number = 2 + node_spec = "vedb.mysql.x4.large" + subnet_id = volcengine_subnet.foo.id + instance_name = "tf-test" + project_name = "testA" + tags { + key = "tftest" + value = "tftest" + } + tags { + key = "tftest2" + value = "tftest2" + } +} + +resource "volcengine_vedb_mysql_database" "foo" { + db_name = "tf-table" + instance_id = volcengine_vedb_mysql_instance.foo.id +} + +resource "volcengine_vedb_mysql_account" "foo" { + account_name = "tftest" + account_password = "93f0cb0614Aab12" + account_type = "Normal" + instance_id = volcengine_vedb_mysql_instance.foo.id + account_privileges { + db_name = volcengine_vedb_mysql_database.foo.db_name + account_privilege = "Custom" + account_privilege_detail = "SELECT,INSERT,DELETE" + } +} +``` +## Argument Reference +The following arguments are supported: +* `account_name` - (Required, ForceNew) Database account name. The account name must meet the following requirements: + The name is unique and within 2 to 32 characters in length. + Consists of lowercase letters, numbers, or underscores (_). + Starts with a lowercase letter and ends with a letter or number. + The name cannot contain certain prohibited words. For detailed information, please refer to prohibited keywords. And certain reserved words such as root, admin, etc. cannot be used. +* `account_password` - (Required) Password of database account. The account password must meet the following requirements: + It can only contain upper and lower case letters, numbers and the following special characters _#!@$%^&*()+=-. +It must be within 8 to 32 characters in length. + It must contain at least three of upper case letters, lower case letters, numbers or special characters. +* `account_type` - (Required, ForceNew) Database account type. Values: +Super: High-privilege account. Only one high-privilege account can be created for an instance. It has all permissions for all databases under this instance and can manage all ordinary accounts and databases. +Normal: Multiple ordinary accounts can be created for an instance. Specific database permissions need to be manually granted to ordinary accounts. +* `instance_id` - (Required, ForceNew) The id of the instance. +* `account_privileges` - (Optional) Database permission information. When the value of AccountType is Super, this parameter does not need to be passed. High-privilege accounts by default have all permissions for all databases under this instance. When the value of AccountType is Normal, it is recommended to pass this parameter to grant specified permissions for specified databases to ordinary accounts. If not set, this account does not have any permissions for any database. + +The `account_privileges` object supports the following: + +* `account_privilege` - (Required) Authorization database privilege types: +ReadWrite: Read and write privilege. + ReadOnly: Read-only privilege. + DDLOnly: Only DDL privilege. + DMLOnly: Only DML privilege. + Custom: Custom privilege. +* `db_name` - (Required) Database name requiring authorization. +* `account_privilege_detail` - (Optional) The specific SQL operation permissions contained in the permission type are separated by English commas (,) between multiple strings. + When used as a request parameter in the CreateDatabase interface, when the AccountPrivilege value is Custom, this parameter is required. Value range (multiple selections allowed): SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, REFERENCES, INDEX, ALTER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, EVENT, TRIGGER. When used as a return parameter in the DescribeDatabases interface, regardless of the value of AccountPrivilege, the details of the SQL operation permissions contained in this permission type are returned. For the specific SQL operation permissions contained in each permission type, please refer to the account permission list. + +## Attributes Reference +In addition to all arguments above, the following attributes are exported: +* `id` - ID of the resource. + + + +## Import +VedbMysqlAccount can be imported using the instance id and account name, e.g. +``` +$ terraform import volcengine_vedb_mysql_account.default vedbm-r3xq0zdl****:testuser + +``` + diff --git a/website/docs/r/vedb_mysql_allowlist.html.markdown b/website/docs/r/vedb_mysql_allowlist.html.markdown new file mode 100644 index 00000000..f34a0d63 --- /dev/null +++ b/website/docs/r/vedb_mysql_allowlist.html.markdown @@ -0,0 +1,38 @@ +--- +subcategory: "VEDB_MYSQL" +layout: "volcengine" +page_title: "Volcengine: volcengine_vedb_mysql_allowlist" +sidebar_current: "docs-volcengine-resource-vedb_mysql_allowlist" +description: |- + Provides a resource to manage vedb mysql allowlist +--- +# volcengine_vedb_mysql_allowlist +Provides a resource to manage vedb mysql allowlist +## Example Usage +```hcl +resource "volcengine_vedb_mysql_allowlist" "foo" { + allow_list_name = "acc-test-allowlist" + allow_list_desc = "acc-test" + allow_list_type = "IPv4" + allow_list = ["192.168.0.0/24", "192.168.1.0/24", "192.168.2.0/24"] +} +``` +## Argument Reference +The following arguments are supported: +* `allow_list_name` - (Required) The name of the allow list. +* `allow_list` - (Required) Enter an IP address or a range of IP addresses in CIDR format. +* `allow_list_desc` - (Optional) The description of the allow list. +* `allow_list_type` - (Optional) The type of IP address in the whitelist. Currently only IPv4 addresses are supported. + +## Attributes Reference +In addition to all arguments above, the following attributes are exported: +* `id` - ID of the resource. +* `allow_list_id` - The id of the allow list. + + +## Import +VedbMysqlAllowlist can be imported using the id, e.g. +``` +$ terraform import volcengine_vedb_mysql_allowlist.default resource_id +``` + diff --git a/website/docs/r/vedb_mysql_allowlist_associate.html.markdown b/website/docs/r/vedb_mysql_allowlist_associate.html.markdown new file mode 100644 index 00000000..2e8374ff --- /dev/null +++ b/website/docs/r/vedb_mysql_allowlist_associate.html.markdown @@ -0,0 +1,77 @@ +--- +subcategory: "VEDB_MYSQL" +layout: "volcengine" +page_title: "Volcengine: volcengine_vedb_mysql_allowlist_associate" +sidebar_current: "docs-volcengine-resource-vedb_mysql_allowlist_associate" +description: |- + Provides a resource to manage vedb mysql allowlist associate +--- +# volcengine_vedb_mysql_allowlist_associate +Provides a resource to manage vedb mysql allowlist associate +## Example Usage +```hcl +resource "volcengine_vedb_mysql_allowlist" "foo" { + allow_list_name = "acc-test-allowlist" + allow_list_desc = "acc-test" + allow_list_type = "IPv4" + allow_list = ["192.168.0.0/24", "192.168.1.0/24", "192.168.2.0/24"] +} + +data "volcengine_zones" "foo" { +} + +resource "volcengine_vpc" "foo" { + vpc_name = "acc-test-vpc" + cidr_block = "172.16.0.0/16" +} + +resource "volcengine_subnet" "foo" { + subnet_name = "acc-test-subnet" + cidr_block = "172.16.0.0/24" + zone_id = data.volcengine_zones.foo.zones[2].id + vpc_id = volcengine_vpc.foo.id +} + + +resource "volcengine_vedb_mysql_instance" "foo" { + charge_type = "PostPaid" + storage_charge_type = "PostPaid" + db_engine_version = "MySQL_8_0" + db_minor_version = "3.0" + node_number = 2 + node_spec = "vedb.mysql.x4.large" + subnet_id = volcengine_subnet.foo.id + instance_name = "tf-test" + project_name = "testA" + tags { + key = "tftest" + value = "tftest" + } + tags { + key = "tftest2" + value = "tftest2" + } +} + +resource "volcengine_vedb_mysql_allowlist_associate" "foo" { + allow_list_id = volcengine_vedb_mysql_allowlist.foo.id + instance_id = volcengine_vedb_mysql_instance.foo.id +} +``` +## Argument Reference +The following arguments are supported: +* `allow_list_id` - (Required, ForceNew) The id of the allow list. +* `instance_id` - (Required, ForceNew) The id of the mysql instance. + +## Attributes Reference +In addition to all arguments above, the following attributes are exported: +* `id` - ID of the resource. + + + +## Import +VedbMysqlAllowlistAssociate can be imported using the instance id and allow list id, e.g. +``` +$ terraform import volcengine_vedb_mysql_allowlist_associate.default vedbm-iqnh3a7z****:acl-d1fd76693bd54e658912e7337d5b**** +``` + diff --git a/website/docs/r/vedb_mysql_backup.html.markdown b/website/docs/r/vedb_mysql_backup.html.markdown new file mode 100644 index 00000000..6c5902ba --- /dev/null +++ b/website/docs/r/vedb_mysql_backup.html.markdown @@ -0,0 +1,82 @@ +--- +subcategory: "VEDB_MYSQL" +layout: "volcengine" +page_title: "Volcengine: volcengine_vedb_mysql_backup" +sidebar_current: "docs-volcengine-resource-vedb_mysql_backup" +description: |- + Provides a resource to manage vedb mysql backup +--- +# volcengine_vedb_mysql_backup +Provides a resource to manage vedb mysql backup +## Example Usage +```hcl +data "volcengine_zones" "foo" { +} + +resource "volcengine_vpc" "foo" { + vpc_name = "acc-test-vpc" + cidr_block = "172.16.0.0/16" +} + +resource "volcengine_subnet" "foo" { + subnet_name = "acc-test-subnet" + cidr_block = "172.16.0.0/24" + zone_id = data.volcengine_zones.foo.zones[2].id + vpc_id = volcengine_vpc.foo.id +} + + +resource "volcengine_vedb_mysql_instance" "foo" { + charge_type = "PostPaid" + storage_charge_type = "PostPaid" + db_engine_version = "MySQL_8_0" + db_minor_version = "3.0" + node_number = 2 + node_spec = "vedb.mysql.x4.large" + subnet_id = volcengine_subnet.foo.id + instance_name = "tf-test" + project_name = "testA" + tags { + key = "tftest" + value = "tftest" + } + tags { + key = "tftest2" + value = "tftest2" + } +} + +resource "volcengine_vedb_mysql_backup" "foo" { + instance_id = volcengine_vedb_mysql_instance.foo.id + backup_policy { + backup_time = "18:00Z-20:00Z" + full_backup_period = "Monday,Tuesday,Wednesday" + backup_retention_period = 8 + } +} +``` +## Argument Reference +The following arguments are supported: +* `instance_id` - (Required, ForceNew) The id of the instance. +* `backup_method` - (Optional, ForceNew) Backup method. Currently, only physical backup is supported. The value is Physical. +* `backup_policy` - (Optional) Data backup strategy for instances. +* `backup_type` - (Optional, ForceNew) Backup type. Currently, only full backup is supported. The value is Full. + +The `backup_policy` object supports the following: + +* `backup_retention_period` - (Required) Data backup retention period, value: 7 to 30 days. +* `backup_time` - (Required) The time for executing the backup task has an interval window of 2 hours and must be an even-hour time. Format: HH:mmZ-HH:mmZ (UTC time). +* `full_backup_period` - (Required) Full backup period. It is recommended to select at least 2 days per week for full backup. Multiple values are separated by English commas (,). Values: Monday: Monday. Tuesday: Tuesday. Wednesday: Wednesday. Thursday: Thursday. Friday: Friday. Saturday: Saturday. Sunday: Sunday. + +## Attributes Reference +In addition to all arguments above, the following attributes are exported: +* `id` - ID of the resource. +* `backup_id` - The id of the backup. + + +## Import +VedbMysqlBackup can be imported using the instance id and backup id, e.g. +``` +$ terraform import volcengine_vedb_mysql_backup.default instanceID:backupId +``` + diff --git a/website/docs/r/vedb_mysql_database.html.markdown b/website/docs/r/vedb_mysql_database.html.markdown new file mode 100644 index 00000000..247ea820 --- /dev/null +++ b/website/docs/r/vedb_mysql_database.html.markdown @@ -0,0 +1,75 @@ +--- +subcategory: "VEDB_MYSQL" +layout: "volcengine" +page_title: "Volcengine: volcengine_vedb_mysql_database" +sidebar_current: "docs-volcengine-resource-vedb_mysql_database" +description: |- + Provides a resource to manage vedb mysql database +--- +# volcengine_vedb_mysql_database +Provides a resource to manage vedb mysql database +## Example Usage +```hcl +data "volcengine_zones" "foo" { +} + +resource "volcengine_vpc" "foo" { + vpc_name = "acc-test-vpc" + cidr_block = "172.16.0.0/16" +} + +resource "volcengine_subnet" "foo" { + subnet_name = "acc-test-subnet" + cidr_block = "172.16.0.0/24" + zone_id = data.volcengine_zones.foo.zones[2].id + vpc_id = volcengine_vpc.foo.id +} + + +resource "volcengine_vedb_mysql_instance" "foo" { + charge_type = "PostPaid" + storage_charge_type = "PostPaid" + db_engine_version = "MySQL_8_0" + db_minor_version = "3.0" + node_number = 2 + node_spec = "vedb.mysql.x4.large" + subnet_id = volcengine_subnet.foo.id + instance_name = "tf-test" + project_name = "testA" + tags { + key = "tftest" + value = "tftest" + } + tags { + key = "tftest2" + value = "tftest2" + } +} + +resource "volcengine_vedb_mysql_database" "foo" { + db_name = "tf-table" + instance_id = volcengine_vedb_mysql_instance.foo.id +} +``` +## Argument Reference +The following arguments are supported: +* `db_name` - (Required, ForceNew) The name of the database. Naming rules: + Unique name. Start with a lowercase letter and end with a letter or number. The length is within 2 to 64 characters. + Consist of lowercase letters, numbers, underscores (_), or hyphens (-). + The name cannot contain certain reserved words. +* `instance_id` - (Required, ForceNew) The id of the instance. +* `character_set_name` - (Optional, ForceNew) Database character set: utf8mb4 (default), utf8, latin1, ascii. + +## Attributes Reference +In addition to all arguments above, the following attributes are exported: +* `id` - ID of the resource. + + + +## Import +VedbMysqlDatabase can be imported using the instance id and database name, e.g. +``` +$ terraform import volcengine_vedb_mysql_database.default vedbm-r3xq0zdl****:testdb + +``` + diff --git a/website/docs/r/vedb_mysql_endpoint.html.markdown b/website/docs/r/vedb_mysql_endpoint.html.markdown new file mode 100644 index 00000000..f007d41a --- /dev/null +++ b/website/docs/r/vedb_mysql_endpoint.html.markdown @@ -0,0 +1,120 @@ +--- +subcategory: "VEDB_MYSQL" +layout: "volcengine" +page_title: "Volcengine: volcengine_vedb_mysql_endpoint" +sidebar_current: "docs-volcengine-resource-vedb_mysql_endpoint" +description: |- + Provides a resource to manage vedb mysql endpoint +--- +# volcengine_vedb_mysql_endpoint +Provides a resource to manage vedb mysql endpoint +## Example Usage +```hcl +data "volcengine_zones" "foo" { +} + +resource "volcengine_vpc" "foo" { + vpc_name = "acc-test-vpc" + cidr_block = "172.16.0.0/16" +} + +resource "volcengine_subnet" "foo" { + subnet_name = "acc-test-subnet" + cidr_block = "172.16.0.0/24" + zone_id = data.volcengine_zones.foo.zones[2].id + vpc_id = volcengine_vpc.foo.id +} + + +resource "volcengine_vedb_mysql_instance" "foo" { + charge_type = "PostPaid" + storage_charge_type = "PostPaid" + db_engine_version = "MySQL_8_0" + db_minor_version = "3.0" + node_number = 2 + node_spec = "vedb.mysql.x4.large" + subnet_id = volcengine_subnet.foo.id + instance_name = "tf-test" + project_name = "testA" + tags { + key = "tftest" + value = "tftest" + } + tags { + key = "tftest2" + value = "tftest2" + } +} +data "volcengine_vedb_mysql_instances" "foo" { + instance_id = volcengine_vedb_mysql_instance.foo.id +} + +resource "volcengine_vedb_mysql_endpoint" "foo" { + endpoint_type = "Custom" + instance_id = volcengine_vedb_mysql_instance.foo.id + node_ids = [data.volcengine_vedb_mysql_instances.foo.instances[0].nodes[0].node_id, data.volcengine_vedb_mysql_instances.foo.instances[0].nodes[1].node_id] + read_write_mode = "ReadWrite" + endpoint_name = "tf-test" + description = "tf test" + master_accept_read_requests = true + distributed_transaction = true + consist_level = "Session" + consist_timeout = 100000 + consist_timeout_action = "ReadMaster" +} +``` +## Argument Reference +The following arguments are supported: +* `endpoint_type` - (Required, ForceNew) Connect endpoint type. The value is fixed as Custom, indicating a custom endpoint. +* `instance_id` - (Required, ForceNew) The id of the instance. +* `node_ids` - (Required) Connect the node IDs associated with the endpoint.The filling rules are as follows: +When the value of ReadWriteMode is ReadWrite, at least two nodes must be passed in, and the master node must be passed in. +When the value of ReadWriteMode is ReadOnly, one or more read-only nodes can be passed in. +* `consist_level` - (Optional) Consistency level. For detailed introduction of consistency level, please refer to consistency level. Value range: +Eventual: eventual consistency. +Session: session consistency. +Global: global consistency. +Description +When the value of ReadWriteMode is ReadWrite, the selectable consistency levels are Eventual, Session (default), and Global. +When the value of ReadWriteMode is ReadOnly, the consistency level is Eventual by default and cannot be changed. +* `consist_timeout_action` - (Optional) Timeout policy after data synchronization timeout of read-only nodes supports the following two policies: +ReturnError: Return SQL error (wait replication complete timeout, please retry). +ReadMaster: Send a request to the master node (default). +Description + This parameter takes effect only when the value of ConsistLevel is Global or Session. +* `consist_timeout` - (Optional) When there is a large delay, the timeout period for read-only nodes to synchronize the latest data, in us. The value range is from 1us to 100000000us, and the default value is 10000us. +Explanation + This parameter takes effect only when the value of ConsistLevel is Global or Session. +* `description` - (Optional) Description information for connecting endpoint. The length cannot exceed 200 characters. +* `distributed_transaction` - (Optional) Set whether to enable transaction splitting. For detailed introduction to transaction splitting, please refer to transaction splitting. Value range: +true: Enabled (default). +false: Disabled. +Description +Only when the value of ReadWriteMode is ReadWrite, is enabling transaction splitting supported. +* `endpoint_name` - (Optional) Connect the endpoint name. The setting rules are as follows: + It cannot start with a number or a hyphen (-). + It can only contain Chinese characters, letters, numbers, underscores (_), and hyphens (-). + The length is 1 to 64 characters. +* `master_accept_read_requests` - (Optional) The master node accepts read requests. Value range: +true: (default) After enabling the master node to accept read functions, non-transactional read requests will be sent to the master node or read-only nodes in a load-balanced mode according to the number of active requests. +false: After disabling the master node from accepting read requests, at this time, the master node only accepts transactional read requests, and non-transactional read requests will not be sent to the master node. +Description +Only when the value of ReadWriteMode is ReadWrite, enabling the master node to accept reads is supported. +* `read_write_mode` - (Optional) Endpoint read-write mode. Values: + ReadWrite: Read and write endpoint. + ReadOnly: Read-only endpoint (default). + +## Attributes Reference +In addition to all arguments above, the following attributes are exported: +* `id` - ID of the resource. +* `endpoint_id` - The id of the endpoint. + + +## Import +VedbMysqlEndpoint can be imported using the instance id:endpoint id, e.g. +``` +$ terraform import volcengine_vedb_mysql_endpoint.default vedbm-iqnh3a7z****:vedbm-2pf2xk5v****-Custom-50yv +``` +Note: The master node endpoint only supports modifying the EndpointName and Description parameters. If values are passed in for other parameters, these values will be ignored without generating an error. +The default endpoint does not support modifying the ReadWriteMode, AutoAddNewNodes, and Nodes parameters. If values are passed in for these parameters, these values will be ignored without generating an error. + diff --git a/website/docs/r/vedb_mysql_endpoint_public_address.html.markdown b/website/docs/r/vedb_mysql_endpoint_public_address.html.markdown new file mode 100644 index 00000000..b6f78f78 --- /dev/null +++ b/website/docs/r/vedb_mysql_endpoint_public_address.html.markdown @@ -0,0 +1,98 @@ +--- +subcategory: "VEDB_MYSQL" +layout: "volcengine" +page_title: "Volcengine: volcengine_vedb_mysql_endpoint_public_address" +sidebar_current: "docs-volcengine-resource-vedb_mysql_endpoint_public_address" +description: |- + Provides a resource to manage vedb mysql endpoint public address +--- +# volcengine_vedb_mysql_endpoint_public_address +Provides a resource to manage vedb mysql endpoint public address +## Example Usage +```hcl +data "volcengine_zones" "foo" { +} + +resource "volcengine_vpc" "foo" { + vpc_name = "acc-test-vpc" + cidr_block = "172.16.0.0/16" +} + +resource "volcengine_subnet" "foo" { + subnet_name = "acc-test-subnet" + cidr_block = "172.16.0.0/24" + zone_id = data.volcengine_zones.foo.zones[2].id + vpc_id = volcengine_vpc.foo.id +} + + +resource "volcengine_vedb_mysql_instance" "foo" { + charge_type = "PostPaid" + storage_charge_type = "PostPaid" + db_engine_version = "MySQL_8_0" + db_minor_version = "3.0" + node_number = 2 + node_spec = "vedb.mysql.x4.large" + subnet_id = volcengine_subnet.foo.id + instance_name = "tf-test" + project_name = "default" + tags { + key = "tftest" + value = "tftest" + } + tags { + key = "tftest2" + value = "tftest2" + } +} +data "volcengine_vedb_mysql_instances" "foo" { + instance_id = volcengine_vedb_mysql_instance.foo.id +} + +resource "volcengine_vedb_mysql_endpoint" "foo" { + endpoint_type = "Custom" + instance_id = volcengine_vedb_mysql_instance.foo.id + node_ids = [data.volcengine_vedb_mysql_instances.foo.instances[0].nodes[0].node_id, data.volcengine_vedb_mysql_instances.foo.instances[0].nodes[1].node_id] + read_write_mode = "ReadWrite" + endpoint_name = "tf-test" + description = "tf test" + master_accept_read_requests = true + distributed_transaction = true + consist_level = "Session" + consist_timeout = 100000 + consist_timeout_action = "ReadMaster" +} + +resource "volcengine_eip_address" "foo" { + billing_type = "PostPaidByBandwidth" + bandwidth = 1 + isp = "ChinaUnicom" + name = "acc-eip" + description = "acc-test" + project_name = "default" +} + +resource "volcengine_vedb_mysql_endpoint_public_address" "foo" { + eip_id = volcengine_eip_address.foo.id + endpoint_id = volcengine_vedb_mysql_endpoint.foo.endpoint_id + instance_id = volcengine_vedb_mysql_instance.foo.id +} +``` +## Argument Reference +The following arguments are supported: +* `eip_id` - (Required, ForceNew) EIP ID that needs to be bound to the instance. +* `endpoint_id` - (Required, ForceNew) The endpoint id. +* `instance_id` - (Required, ForceNew) The instance id. + +## Attributes Reference +In addition to all arguments above, the following attributes are exported: +* `id` - ID of the resource. + + + +## Import +VedbMysqlEndpointPublicAddress can be imported using the instance id, endpoint id and the eip id, e.g. +``` +$ terraform import volcengine_vedb_mysql_endpoint_public_address.default vedbm-iqnh3a7z****:vedbm-2pf2xk5v****-Custom-50yv:eip-xxxx +``` + diff --git a/website/docs/r/vedb_mysql_instance.html.markdown b/website/docs/r/vedb_mysql_instance.html.markdown new file mode 100644 index 00000000..c00e4601 --- /dev/null +++ b/website/docs/r/vedb_mysql_instance.html.markdown @@ -0,0 +1,119 @@ +--- +subcategory: "VEDB_MYSQL" +layout: "volcengine" +page_title: "Volcengine: volcengine_vedb_mysql_instance" +sidebar_current: "docs-volcengine-resource-vedb_mysql_instance" +description: |- + Provides a resource to manage vedb mysql instance +--- +# volcengine_vedb_mysql_instance +Provides a resource to manage vedb mysql instance +## Notice +When Destroy this resource,If the resource charge type is PrePaid,Please unsubscribe the resource +in [Volcengine Console](https://console.volcengine.com/finance/unsubscribe/),when complete console operation,yon can +use 'terraform state rm ${resourceId}' to remove. +## Example Usage +```hcl +data "volcengine_zones" "foo" { +} + +resource "volcengine_vpc" "foo" { + vpc_name = "acc-test-vpc" + cidr_block = "172.16.0.0/16" +} + +resource "volcengine_subnet" "foo" { + subnet_name = "acc-test-subnet" + cidr_block = "172.16.0.0/24" + zone_id = data.volcengine_zones.foo.zones[2].id + vpc_id = volcengine_vpc.foo.id +} + + +resource "volcengine_vedb_mysql_instance" "foo" { + charge_type = "PostPaid" + storage_charge_type = "PostPaid" + db_engine_version = "MySQL_8_0" + db_minor_version = "3.0" + node_number = 2 + node_spec = "vedb.mysql.x4.large" + subnet_id = volcengine_subnet.foo.id + instance_name = "tf-test" + project_name = "default" + tags { + key = "tftest" + value = "tftest" + } +} +``` +## Argument Reference +The following arguments are supported: +* `charge_type` - (Required) Calculate the billing type. When calculating the billing type during instance creation, the possible values are as follows: +PostPaid: Pay-as-you-go (postpaid). +PrePaid: Monthly or yearly subscription (prepaid). +* `db_engine_version` - (Required, ForceNew) Database engine version, with a fixed value of MySQL_8_0. +* `node_number` - (Required) Number of instance nodes. The value range is from 2 to 16. +* `node_spec` - (Required) Node specification code of an instance. +* `subnet_id` - (Required, ForceNew) Subnet ID of the veDB Mysql instance. +* `auto_renew` - (Optional) Whether to automatically renew under the prepaid scenario. Values: +true: Automatically renew. +false: Do not automatically renew. +Description: +When the value of ChargeType (billing type) is PrePaid (monthly/yearly package), this parameter is required. +* `db_minor_version` - (Optional, ForceNew) veDB MySQL minor version. For detailed instructions on version numbers, please refer to Version Number Management. + 3.0 (default): veDB MySQL stable version, 100% compatible with MySQL 8.0. + 3.1: Natively supports HTAP application scenarios and accelerates complex queries. + 3.2: Natively supports HTAP application scenarios and accelerates complex queries. In addition, it has built-in cold data archiving capabilities. It can archive data with low-frequency access to object storage TOS to reduce storage costs. +* `db_time_zone` - (Optional, ForceNew) Time zone. Support UTC -12:00 ~ +13:00. When importing resources, this attribute will not be imported. If this attribute is set, please use lifecycle and ignore_changes ignore changes in fields. +* `instance_name` - (Optional) Instance name. Naming rules: +It cannot start with a number or a hyphen (-). +It can only contain Chinese characters, letters, numbers, underscores (_), and hyphens (-). +The length must be within 1 to 128 characters. +Description +If the instance name is not filled in, the instance ID will be used as the instance name. +When creating instances in batches, if an instance name is passed in, a serial number will be automatically added after the instance name. +* `lower_case_table_names` - (Optional, ForceNew) Whether table names are case-sensitive. The default value is 1. Value range: +0: Table names are case-sensitive. The backend stores them according to the actual table name. +1: (default) Table names are not case-sensitive. The backend stores them by converting table names to lowercase letters. +Description: +This rule cannot be modified after creating an instance. Please set it reasonably according to business requirements. +* `period_unit` - (Optional) Purchase cycle in prepaid scenarios. +Month: Monthly package. +Year: Annual package. +Description: +When the value of ChargeType (computing billing type) is PrePaid (monthly or annual package), this parameter is required. +* `period` - (Optional) Purchase duration in prepaid scenarios. +Description: +When the value of ChargeType (computing billing type) is PrePaid (monthly/yearly package), this parameter is required. +* `port` - (Optional, ForceNew) Specify the private network port number for the connection terminal created by default for the instance. The default value is 3306, and the value range is 1000 to 65534. +Note: +This configuration item is only effective for the primary node terminal, default terminal, and HTAP cluster terminal. That is, after the instance is created successfully, for the newly created custom terminal, the port number is still 3306 by default. +After the instance is created successfully, you can also modify the port number at any time. Currently, only modification through the console is supported. +* `pre_paid_storage_in_gb` - (Optional) Storage size in prepaid scenarios. +Description: When the value of StorageChargeType (storage billing type) is PrePaid (monthly/yearly prepaid), this parameter is required. +* `project_name` - (Optional) Project name of the instance. When this parameter is left blank, the newly created instance is added to the default project by default. +* `storage_charge_type` - (Optional) Storage billing type. When this parameter is not passed, the storage billing type defaults to be the same as the computing billing type. The values are as follows: +PostPaid: Pay-as-you-go (postpaid). +PrePaid: Monthly or yearly subscription (prepaid). +Note +When the computing billing type is PostPaid, the storage billing type can only be PostPaid. +When the computing billing type is PrePaid, the storage billing type can be PrePaid or PostPaid. +* `tags` - (Optional) Tags. + +The `tags` object supports the following: + +* `key` - (Required) The Key of Tags. +* `value` - (Required) The Value of Tags. + +## Attributes Reference +In addition to all arguments above, the following attributes are exported: +* `id` - ID of the resource. + + + +## Import +VedbMysqlInstance can be imported using the id, e.g. +``` +$ terraform import volcengine_vedb_mysql_instance.default resource_id +``` + diff --git a/website/volcengine.erb b/website/volcengine.erb index c752e02f..56c82459 100644 --- a/website/volcengine.erb +++ b/website/volcengine.erb @@ -1639,6 +1639,63 @@ +