Skip to content

Commit

Permalink
feat(mysql): add refreshFromOutput diags (#475)
Browse files Browse the repository at this point in the history
* refactor: change error to diags

* fix: change vpc, subnet to resource

* feat: add refreshFromOutput diags
  • Loading branch information
dusdjhyeon authored Nov 5, 2024
1 parent d035d05 commit 13e9e9d
Show file tree
Hide file tree
Showing 6 changed files with 82 additions and 97 deletions.
23 changes: 9 additions & 14 deletions internal/service/mysql/mysql_databases.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"github.com/hashicorp/terraform-plugin-framework-validators/listvalidator"
"github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator"
"github.com/hashicorp/terraform-plugin-framework/attr"
"github.com/hashicorp/terraform-plugin-framework/diag"
"github.com/hashicorp/terraform-plugin-framework/path"
"github.com/hashicorp/terraform-plugin-framework/resource"
"github.com/hashicorp/terraform-plugin-framework/resource/schema"
Expand Down Expand Up @@ -151,11 +152,8 @@ func (r *mysqlDatabasesResource) Create(ctx context.Context, req resource.Create
return
}

if err := plan.refreshFromOutput(ctx, output, plan.MysqlInstanceNo.ValueString()); err != nil {
resp.Diagnostics.AddError(
"Error while getting output values of mysql databases list",
err.Error(),
)
if diags := plan.refreshFromOutput(ctx, output, plan.MysqlInstanceNo.ValueString()); diags.HasError() {
resp.Diagnostics.AddError("READING ERROR", "refreshFromOutput error")
return
}

Expand All @@ -181,11 +179,8 @@ func (r *mysqlDatabasesResource) Read(ctx context.Context, req resource.ReadRequ
return
}

if err := state.refreshFromOutput(ctx, output, state.MysqlInstanceNo.ValueString()); err != nil {
resp.Diagnostics.AddError(
"Error while getting output values of mysql databases list",
err.Error(),
)
if diags := state.refreshFromOutput(ctx, output, state.MysqlInstanceNo.ValueString()); diags.HasError() {
resp.Diagnostics.AddError("READING ERROR", "refreshFromOutput error")
return
}

Expand Down Expand Up @@ -293,7 +288,7 @@ func (r mysqlDatabase) AttrTypes() map[string]attr.Type {
}
}

func (r *mysqlDatabasesResourceModel) refreshFromOutput(ctx context.Context, output []*vmysql.CloudMysqlDatabase, instance string) error {
func (r *mysqlDatabasesResourceModel) refreshFromOutput(ctx context.Context, output []*vmysql.CloudMysqlDatabase, instance string) diag.Diagnostics {
r.ID = types.StringValue(instance)
r.MysqlInstanceNo = types.StringValue(instance)

Expand All @@ -305,9 +300,9 @@ func (r *mysqlDatabasesResourceModel) refreshFromOutput(ctx context.Context, out
databaseList = append(databaseList, mysqlDb)
}

mysqlDatabases, err := types.ListValueFrom(ctx, types.ObjectType{AttrTypes: mysqlDatabase{}.AttrTypes()}, databaseList)
if err != nil {
return fmt.Errorf("error creating ListValue for Mysql Databases: %s", err)
mysqlDatabases, diags := types.ListValueFrom(ctx, types.ObjectType{AttrTypes: mysqlDatabase{}.AttrTypes()}, databaseList)
if diags.HasError() {
return diags
}

r.MysqlDatabaseList = mysqlDatabases
Expand Down
16 changes: 7 additions & 9 deletions internal/service/mysql/mysql_databases_data_source.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"github.com/hashicorp/terraform-plugin-framework/attr"
"github.com/hashicorp/terraform-plugin-framework/datasource"
"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
"github.com/hashicorp/terraform-plugin-framework/diag"
"github.com/hashicorp/terraform-plugin-framework/types"
"github.com/hashicorp/terraform-plugin-log/tflog"
"github.com/terraform-providers/terraform-provider-ncloud/internal/common"
Expand Down Expand Up @@ -109,11 +110,8 @@ func (d *mysqlDatabasesDataSource) Read(ctx context.Context, req datasource.Read

mysqlDbList := flattenMysqlDatabases(output)
fillteredList := common.FilterModels(ctx, data.Filters, mysqlDbList)
if err := data.refreshFromOutput(ctx, fillteredList, data.MysqlInstanceNo.ValueString()); err != nil {
resp.Diagnostics.AddError(
"Error while getting output values of mysql databases list",
err.Error(),
)
if diags := data.refreshFromOutput(ctx, fillteredList, data.MysqlInstanceNo.ValueString()); diags != nil {
resp.Diagnostics.AddError("READING ERROR", "refreshFromOutput error")
return
}

Expand Down Expand Up @@ -220,12 +218,12 @@ func flattenMysqlDatabases(list []*vmysql.CloudMysqlDatabase) []*mysqlDb {
return outputs
}

func (d *mysqlDatabasesDataSourceModel) refreshFromOutput(ctx context.Context, output []*mysqlDb, instance string) error {
func (d *mysqlDatabasesDataSourceModel) refreshFromOutput(ctx context.Context, output []*mysqlDb, instance string) diag.Diagnostics {
d.ID = types.StringValue(instance)
d.MysqlInstanceNo = types.StringValue(instance)
dbListValue, err := types.ListValueFrom(ctx, types.ObjectType{AttrTypes: mysqlDb{}.attrTypes()}, output)
if err != nil {
return fmt.Errorf("error creating ListValue for Mysql Databases: %s", err)
dbListValue, diags := types.ListValueFrom(ctx, types.ObjectType{AttrTypes: mysqlDb{}.attrTypes()}, output)
if diags.HasError() {
return diags
}
d.MysqlDatabaseList = dbListValue

Expand Down
16 changes: 11 additions & 5 deletions internal/service/mysql/mysql_databases_data_source_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,16 +36,22 @@ func TestAccDataSourceNcloudMysqlDatabases_vpc_basic(t *testing.T) {

func testAccDataSourceMysqlDatabasesConfig(testName string) string {
return fmt.Sprintf(`
data "ncloud_vpc" "test_vpc" {
id = "75658"
resource "ncloud_vpc" "test_vpc" {
name = "%[1]s"
ipv4_cidr_block = "10.5.0.0/16"
}
data "ncloud_subnet" "test_subnet" {
id = "172709"
resource "ncloud_subnet" "test_subnet" {
vpc_no = ncloud_vpc.test_vpc.vpc_no
name = "%[1]s"
subnet = "10.5.0.0/24"
zone = "KR-2"
network_acl_no = ncloud_vpc.test_vpc.default_network_acl_no
subnet_type = "PUBLIC"
}
resource "ncloud_mysql" "mysql" {
subnet_no = data.ncloud_subnet.test_subnet.id
subnet_no = ncloud_subnet.test_subnet.id
service_name = "%[1]s"
server_name_prefix = "testprefix"
user_name = "testusername"
Expand Down
16 changes: 11 additions & 5 deletions internal/service/mysql/mysql_databases_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,16 +43,22 @@ func TestAccResourceNcloudMysqlDatabases_vpc_basic(t *testing.T) {

func testAccMysqlDatabasesConfig(testMysqlName string) string {
return fmt.Sprintf(`
data "ncloud_vpc" "test_vpc" {
id = "75658"
resource "ncloud_vpc" "test_vpc" {
name = "%[1]s"
ipv4_cidr_block = "10.5.0.0/16"
}
data "ncloud_subnet" "test_subnet" {
id = "172709"
resource "ncloud_subnet" "test_subnet" {
vpc_no = ncloud_vpc.test_vpc.vpc_no
name = "%[1]s"
subnet = "10.5.0.0/24"
zone = "KR-2"
network_acl_no = ncloud_vpc.test_vpc.default_network_acl_no
subnet_type = "PUBLIC"
}
resource "ncloud_mysql" "mysql" {
subnet_no = data.ncloud_subnet.test_subnet.id
subnet_no = ncloud_subnet.test_subnet.id
service_name = "%[1]s"
server_name_prefix = "testprefix"
user_name = "testusername"
Expand Down
92 changes: 37 additions & 55 deletions internal/service/mysql/mysql_users.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,13 @@ package mysql
import (
"context"
"fmt"
"log"
"regexp"
"time"

"github.com/NaverCloudPlatform/ncloud-sdk-go-v2/ncloud"
"github.com/NaverCloudPlatform/ncloud-sdk-go-v2/services/vmysql"
"github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator"
"github.com/hashicorp/terraform-plugin-framework/attr"
"github.com/hashicorp/terraform-plugin-framework/diag"
"github.com/hashicorp/terraform-plugin-framework/path"
"github.com/hashicorp/terraform-plugin-framework/resource"
"github.com/hashicorp/terraform-plugin-framework/resource/schema"
Expand All @@ -22,7 +21,6 @@ import (
"github.com/hashicorp/terraform-plugin-framework/types"
"github.com/hashicorp/terraform-plugin-framework/types/basetypes"
"github.com/hashicorp/terraform-plugin-log/tflog"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry"
"github.com/terraform-providers/terraform-provider-ncloud/internal/common"
"github.com/terraform-providers/terraform-provider-ncloud/internal/conn"
"github.com/terraform-providers/terraform-provider-ncloud/internal/framework"
Expand Down Expand Up @@ -105,7 +103,7 @@ func (r *mysqlUsersResource) Schema(_ context.Context, _ resource.SchemaRequest,
Required: true,
Sensitive: true,
PlanModifiers: []planmodifier.String{
stringplanmodifier.RequiresReplace(),
stringplanmodifier.UseStateForUnknown(),
},
Validators: []validator.String{
stringvalidator.All(
Expand All @@ -120,7 +118,7 @@ func (r *mysqlUsersResource) Schema(_ context.Context, _ resource.SchemaRequest,
"authority": schema.StringAttribute{
Required: true,
PlanModifiers: []planmodifier.String{
stringplanmodifier.RequiresReplace(),
stringplanmodifier.UseStateForUnknown(),
},
Validators: []validator.String{
stringvalidator.OneOf([]string{"READ", "CRUD", "DDL"}...),
Expand All @@ -130,7 +128,7 @@ func (r *mysqlUsersResource) Schema(_ context.Context, _ resource.SchemaRequest,
Optional: true,
Computed: true,
PlanModifiers: []planmodifier.Bool{
boolplanmodifier.RequiresReplace(),
boolplanmodifier.UseStateForUnknown(),
},
Default: booldefault.StaticBool(true),
},
Expand Down Expand Up @@ -190,7 +188,15 @@ func (r *mysqlUsersResource) Create(ctx context.Context, req resource.CreateRequ
return
}

plan.refreshFromOutput(ctx, output, plan.MysqlInstanceNo.ValueString())
if output == nil {
resp.State.RemoveResource(ctx)
return
}

if diags := plan.refreshFromOutput(ctx, output, plan); diags.HasError() {
resp.Diagnostics.AddError("READING ERROR", "refreshFromOutput error")
return
}
resp.Diagnostics.Append(resp.State.Set(ctx, plan)...)
}

Expand All @@ -213,11 +219,11 @@ func (r *mysqlUsersResource) Read(ctx context.Context, req resource.ReadRequest,
return
}

state.refreshFromOutput(ctx, output, state.MysqlInstanceNo.ValueString())
resp.Diagnostics.Append(resp.State.Set(ctx, &state)...)
if resp.Diagnostics.HasError() {
if diags := state.refreshFromOutput(ctx, output, state); diags.HasError() {
resp.Diagnostics.AddError("READING ERROR", "refreshFromOutput error")
return
}
resp.Diagnostics.Append(resp.State.Set(ctx, &state)...)
}

func (r *mysqlUsersResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) {
Expand Down Expand Up @@ -262,7 +268,15 @@ func (r *mysqlUsersResource) Update(ctx context.Context, req resource.UpdateRequ
return
}

state.refreshFromOutput(ctx, output, state.ID.String())
if output == nil {
resp.State.RemoveResource(ctx)
return
}

if diags := state.refreshFromOutput(ctx, output, state); diags.HasError() {
resp.Diagnostics.AddError("READING ERROR", "refreshFromOutput error")
return
}
}

resp.Diagnostics.Append(resp.State.Set(ctx, state)...)
Expand Down Expand Up @@ -295,42 +309,6 @@ func (r *mysqlUsersResource) Delete(ctx context.Context, req resource.DeleteRequ
return
}
tflog.Info(ctx, "DeleteMysqlUserList response="+common.MarshalUncheckedString(response))

if err := waitMysqlUsersDeletion(ctx, r.config, state.ID.ValueString(), common.ConvertToStringList(state.MysqlUserList, "name")); err != nil {
resp.Diagnostics.AddError("WAITING FOR DELETE ERROR", err.Error())
}
}

func waitMysqlUsersDeletion(ctx context.Context, config *conn.ProviderConfig, id string, users []string) error {
stateConf := &retry.StateChangeConf{
Pending: []string{DELETING},
Target: []string{DELETED},
Refresh: func() (interface{}, string, error) {
userList, err := GetMysqlUserList(ctx, config, id, users)
if err != nil {
return 0, "", err
}

if len(userList) > 1 {
return userList, DELETING, nil
}

if len(userList) == 1 || userList == nil {
return userList, DELETED, nil
}

return 0, "", fmt.Errorf("error occurred while waiting to delete mysql user")
},
Timeout: conn.DefaultTimeout,
Delay: 1 * time.Minute,
MinTimeout: 3 * time.Second,
}

if _, err := stateConf.WaitForStateContext(ctx); err != nil {
return fmt.Errorf("error waiting for mysql user (%s) to become terminating: %s", id, err)
}

return nil
}

func GetMysqlUserList(ctx context.Context, config *conn.ProviderConfig, id string, users []string) ([]*vmysql.CloudMysqlUser, error) {
Expand Down Expand Up @@ -403,36 +381,40 @@ type MysqlUser struct {
func (r MysqlUser) AttrTypes() map[string]attr.Type {
return map[string]attr.Type{
"name": types.StringType,
"password": types.StringType,
"host_ip": types.StringType,
"authority": types.StringType,
"is_system_table_access": types.BoolType,
}
}

func (r *mysqlUsersResourceModel) refreshFromOutput(ctx context.Context, output []*vmysql.CloudMysqlUser, instance string) {
r.ID = types.StringValue(instance)
r.MysqlInstanceNo = types.StringValue(instance)
func (r *mysqlUsersResourceModel) refreshFromOutput(ctx context.Context, output []*vmysql.CloudMysqlUser, resourceModel mysqlUsersResourceModel) diag.Diagnostics {
r.ID = resourceModel.ID
r.MysqlInstanceNo = resourceModel.MysqlInstanceNo

var userList []MysqlUser

for _, user := range output {
for idx, user := range output {
pswd := resourceModel.MysqlUserList.Elements()[idx].(types.Object).Attributes()
mysqlUser := MysqlUser{
UserName: types.StringPointerValue(user.UserName),
HostIp: types.StringPointerValue(user.HostIp),
Authority: types.StringPointerValue(user.Authority),
IsSystemTableAccess: types.BoolPointerValue(user.IsSystemTableAccess),
UserPassword: pswd["password"].(types.String),
}

userList = append(userList, mysqlUser)
}

mysqlUsers, err := types.ListValueFrom(ctx, types.ObjectType{AttrTypes: MysqlUser{}.AttrTypes()}, userList)
if err != nil {
log.Printf("Error converting user list: %v", err)
return
mysqlUsers, diags := types.ListValueFrom(ctx, types.ObjectType{AttrTypes: MysqlUser{}.AttrTypes()}, userList)
if diags.HasError() {
return diags
}

r.MysqlUserList = mysqlUsers

return nil
}

func convertToCloudMysqlUserParameter(values basetypes.ListValue) []*vmysql.CloudMysqlUserParameter {
Expand Down
16 changes: 7 additions & 9 deletions internal/service/mysql/mysql_users_data_source.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"github.com/hashicorp/terraform-plugin-framework/attr"
"github.com/hashicorp/terraform-plugin-framework/datasource"
"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
"github.com/hashicorp/terraform-plugin-framework/diag"
"github.com/hashicorp/terraform-plugin-framework/path"
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
"github.com/hashicorp/terraform-plugin-framework/types"
Expand Down Expand Up @@ -141,11 +142,8 @@ func (d *mysqlUsersDataSource) Read(ctx context.Context, req datasource.ReadRequ

mysqlUserList := flattenMysqlUsers(output)
fillteredList := common.FilterModels(ctx, data.Filters, mysqlUserList)
if err = data.refreshFromOutput(ctx, fillteredList, data.MysqlInstanceNo.ValueString()); err != nil {
resp.Diagnostics.AddError(
"Error while getting output values of mysql users",
err.Error(),
)
if diags := data.refreshFromOutput(ctx, fillteredList, data.MysqlInstanceNo.ValueString()); diags.HasError() {
resp.Diagnostics.AddError("READING ERROR", "refreshFromOutput error")
return
}

Expand Down Expand Up @@ -262,12 +260,12 @@ func flattenMysqlUsers(list []*vmysql.CloudMysqlUser) []*mysqlUser {
return outputs
}

func (d *mysqlUsersDataSourceModel) refreshFromOutput(ctx context.Context, output []*mysqlUser, instance string) error {
func (d *mysqlUsersDataSourceModel) refreshFromOutput(ctx context.Context, output []*mysqlUser, instance string) diag.Diagnostics {
d.ID = types.StringValue(instance)
d.MysqlInstanceNo = types.StringValue(instance)
userListValue, err := types.ListValueFrom(ctx, types.ObjectType{AttrTypes: mysqlUser{}.attrTypes()}, output)
if err != nil {
return fmt.Errorf("error creating ListValue for userList: %s", err)
userListValue, diags := types.ListValueFrom(ctx, types.ObjectType{AttrTypes: mysqlUser{}.attrTypes()}, output)
if diags.HasError() {
return diags
}
d.MysqlUserList = userListValue
return nil
Expand Down

0 comments on commit 13e9e9d

Please sign in to comment.