From 3b3a938f2a9f6f1b27d7754223341ca3217cfc36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Torres=20Cogollo?= Date: Tue, 3 Jun 2025 17:22:22 +0200 Subject: [PATCH 1/4] feat: Support importing role grants --- mysql/resource_grant.go | 20 +++++++++++++++----- website/docs/r/grant.html.markdown | 4 ++++ 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/mysql/resource_grant.go b/mysql/resource_grant.go index 4ac1541c..892facaa 100644 --- a/mysql/resource_grant.go +++ b/mysql/resource_grant.go @@ -676,11 +676,19 @@ func ImportGrant(ctx context.Context, d *schema.ResourceData, meta interface{}) Host: host, } - desiredGrant := &TablePrivilegeGrant{ - Database: database, - Table: table, - Grant: grantOption, - UserOrRole: userOrRole, + var desiredGrant MySQLGrant + if strings.HasSuffix(d.Id(), ";r") { + desiredGrant = &RoleGrant{ + UserOrRole: userOrRole, + Grant: grantOption, + } + } else { + desiredGrant = &TablePrivilegeGrant{ + Database: database, + Table: table, + Grant: grantOption, + UserOrRole: userOrRole, + } } db, err := getDatabaseFromMeta(ctx, meta) @@ -721,6 +729,8 @@ func setDataFromGrant(grant MySQLGrant, d *schema.ResourceData) *schema.Resource d.Set("grant", grant.GrantOption()) d.Set("roles", roleGrant.Roles) d.Set("tls_option", roleGrant.TLSOption) + d.Set("table", "*") // Role grants do not have a table, but we keep the default for consistency + d.Set("database", "*") // Role grants do not have a database, but we keep the default for consistency } else { panic("Unknown grant type") } diff --git a/website/docs/r/grant.html.markdown b/website/docs/r/grant.html.markdown index a756706d..0163b184 100644 --- a/website/docs/r/grant.html.markdown +++ b/website/docs/r/grant.html.markdown @@ -89,6 +89,7 @@ No further attributes are exported. Grants can be imported using user, host, database and table. For grants without explicit database or tables, use `*`. +For role grants, append `;r` as a suffix to the import id. You can also add an extra at sign `@` to the import definition to specify the grant contains WITH GRANT OPTION. @@ -97,6 +98,9 @@ the grant contains WITH GRANT OPTION. $ terraform import mysql_grant.example user@host@database@table $ terraform import mysql_grant.all_db user@host@*@* +# Import a role grant +$ terraform import mysql_grant.role user@host@database@table;r + # Import the first example with grant option $ terraform import mysql_grant.example user@host@database@table@ ``` From 9d676523792dd1a4356155dfa8476bba8e1f6386 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Torres=20Cogollo?= Date: Tue, 3 Jun 2025 17:44:11 +0200 Subject: [PATCH 2/4] Dont block tables and databases for role grants --- mysql/resource_grant.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/mysql/resource_grant.go b/mysql/resource_grant.go index 892facaa..91854971 100644 --- a/mysql/resource_grant.go +++ b/mysql/resource_grant.go @@ -729,8 +729,6 @@ func setDataFromGrant(grant MySQLGrant, d *schema.ResourceData) *schema.Resource d.Set("grant", grant.GrantOption()) d.Set("roles", roleGrant.Roles) d.Set("tls_option", roleGrant.TLSOption) - d.Set("table", "*") // Role grants do not have a table, but we keep the default for consistency - d.Set("database", "*") // Role grants do not have a database, but we keep the default for consistency } else { panic("Unknown grant type") } From 2534074758eb07d3682d993773fd5661ae893ffa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Torres=20Cogollo?= Date: Tue, 3 Jun 2025 18:07:05 +0200 Subject: [PATCH 3/4] Literal import table and database from import string --- mysql/resource_grant.go | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/mysql/resource_grant.go b/mysql/resource_grant.go index 91854971..92eee52e 100644 --- a/mysql/resource_grant.go +++ b/mysql/resource_grant.go @@ -704,6 +704,15 @@ func ImportGrant(ctx context.Context, d *schema.ResourceData, meta interface{}) if foundGrant.ConflictsWithGrant(desiredGrant) { res := resourceGrant().Data(nil) setDataFromGrant(foundGrant, res) + if _, ok := desiredGrant.(*RoleGrant); ok { + /* + Import database and table for role grants literally for backwards compatibility. + Role grants do not have a database or table, but we still set them here to avoid + making existing resources to "force replacement". + */ + res.Set("database", database) + res.Set("table", table) + } return []*schema.ResourceData{res}, nil } } From 960b09a0f6a0e4583cc72d76fefa7576018dce75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Torres=20Cogollo?= Date: Wed, 4 Jun 2025 12:42:14 +0200 Subject: [PATCH 4/4] Fix table import with role import modifier --- mysql/resource_grant.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mysql/resource_grant.go b/mysql/resource_grant.go index 92eee52e..812a034d 100644 --- a/mysql/resource_grant.go +++ b/mysql/resource_grant.go @@ -660,7 +660,7 @@ func isNonExistingGrant(err error) bool { } func ImportGrant(ctx context.Context, d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { - userHostDatabaseTable := strings.Split(d.Id(), "@") + userHostDatabaseTable := strings.Split(strings.TrimSuffix(d.Id(), ";r"), "@") if len(userHostDatabaseTable) != 4 && len(userHostDatabaseTable) != 5 { return nil, fmt.Errorf("wrong ID format %s - expected user@host@database@table (and optionally ending @ to signify grant option) where some parts can be empty)", d.Id())