-
Notifications
You must be signed in to change notification settings - Fork 51
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix grant import #118
Fix grant import #118
Conversation
This fixes the issue described in petoju#112 where it's not possible to import some grants. In short, it: - Adds an additional type for parsing the grant resource from data, `desiredProcedureGrant`, separating it from `desiredGrant`, which now becomes `desiredTableGrant`. This is used when trying to find a conflict and can probably be made a bit more generic, but it's likely outside the scope of this change (see below) - Refactors the old `formatDatabaseName` into `produceGrantId` which, as the name says, produced the grant id that is going to be used by the provider. - Sets some additional required fields for importing the grants, the most important one being the `id` which was missing and causing the errors that were seen in the issue above. It also fixes a typo in the docs that I introduced earlier. There are a few things worth noting: - Role grants are not covered. I don't currently have a use case for that, hence no good way of testing it properly. - As mentioned before, there are parts of the code that could be refactored to be more generic. That being said, it would require implementing the fixes for role grants as well to write it in such a way that it would be properly generic.
@@ -3,14 +3,15 @@ package mysql | |||
import ( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you please create a test to catch this case / issue?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've fixed the existing ones. Anything else you think should be added?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Generally when you want to fix a regression, there should be a new test catching the very issue you are trying to fix.
So that means you should test importing (I know we don't test it anywhere, but still). And ideally, you should leave all previous tests in place. Or fix them, if there is any error there - but there should be some rationale when removing tests.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think it was a regression in the sense that a feature existed and it stopped working. It was, as I understand, a new issue that was implemented that never really worked. I think the current test is reasonable, ti was just built in a way that worked with the implementation, but that was not working in the first place. I think the current test covers the implementation and I'm not sure what sort of regression, specifically, we'd need to cover.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the bug #112 , you described
terraform import mysql_grant.foo_grant_local 'foo_user@localhost@test_db@*'
stopped working. Cannot you test import exactly like that here?
I'd do it based on
https://developer.hashicorp.com/terraform/plugin/sdkv2/resources/import#resource-acceptance-testing-implementation
I'm not completely sure how it works - so if that's too difficult and once I find some time, I can also try looking at that.
@@ -888,21 +889,6 @@ func TestAccGrantOnProcedure(t *testing.T) { | |||
prepareProcedure(dbName, procedureName), | |||
), | |||
}, | |||
{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's wrong with this test? I believe it should stay and possibly be fixed if there's something wrong.
I tried running with it and it shows some issues you'd see, if you ran it manually with config.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My understanding—but keep in mind I'm not an expert on the matter—is that semantically it makes no sense to provide procedure grants with tables, so the test was not meaningful. I couldn't find any references online to such a scenario either, so please do correct me if I'm missing something. Again, I'm not an expert on this so there's a good chance I'm wrong :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This test needs to remain. Although it does make no sense semantically, this is something that was supported by the deprecated Hashicorp mysql provider, and has made its way into other modules:
I think the fix for this (as described in that issue), is that we need to introduce a v2 of the mysql_grant
resource, ideally specific to each type (eg. mysql_table_grant
, mysql_procedure_grant
, etc).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Got it. I couldn't find a way to identify how the object is defined in terraform in the code so that I can build the resource accordingly. Are there any downsides to normalising it? I mean, if the object is parsed correctly and the representation is not crucial, can we just pick one and go with it?
From what I tested, regardless of how the terraform object is defined, we can use either of the formats and it works the same way
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I mean, if the object is parsed correctly and the representation is not crucial, can we just pick one and go with it?
We cannot do it easily like this.
We could do it, if we:
- Preserve the backwards compatibility with whatever was there.
- Write custom DiffSuppressFunc so that this change won't cause a persistent diff.
That's one way to solve the issue. That said, this test needs to remain as it reveals and issue that you introduced and it would pass if there was no diff to the user.
As Derek has pointed out, the best way to solve it would be to introduce mysql_table_grant
/ mysql_procedure_grant
- but that also removes backwards compatibility.
@@ -3,14 +3,15 @@ package mysql | |||
import ( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Generally when you want to fix a regression, there should be a new test catching the very issue you are trying to fix.
So that means you should test importing (I know we don't test it anywhere, but still). And ideally, you should leave all previous tests in place. Or fix them, if there is any error there - but there should be some rationale when removing tests.
desiredGrant := &TablePrivilegeGrant{ | ||
desiredTableGrant := &TablePrivilegeGrant{ | ||
Database: database, | ||
Table: table, | ||
Table: tableOrCallable, | ||
Grant: grantOption, | ||
UserOrRole: userOrRole, | ||
} | ||
|
||
desiredProcedureGrant := &ProcedurePrivilegeGrant{ | ||
Database: database, | ||
CallableName: tableOrCallable, | ||
Grant: grantOption, | ||
UserOrRole: userOrRole, | ||
ObjectT: kProcedure, | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am wondering if we could make this a bit simpler by parsing the tableOrCallable
directly:
var desiredGrant *MySQLGrant = nil
if kReProcedureWithoutDatabase.MatchString(database) {
desiredGrant = &ProcedurePrivilegeGrant{ ... }
} else {
desiredGrant = &TablePrivilegeGrant{ ... }
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My understanding is that we don't have this in formation at this point—database
is derived from the id string being imported, and the way it's constructed now does not expose this information. My initial approach was to do something like this but I couldn't find a clean way.
@@ -688,20 +697,42 @@ func ImportGrant(ctx context.Context, d *schema.ResourceData, meta interface{}) | |||
return results, nil | |||
} | |||
|
|||
func produceGrantId(database string, username string, host string) string { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems potentially redundant with the GetId
interface of MySQLGrant
. Why do we need both?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's right! I don't think we do! Thanks for pointing that out.
database := procedureGrant.Database | ||
id := produceGrantId(database, userOrRole.Name, userOrRole.Host) | ||
d.SetId(id) | ||
d.Set("database", fmt.Sprintf("PROCEDURE %s.%s", database, procedureGrant.CallableName)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not a safe operation, because the user can specify the database as in Example 2:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see, I think I might be able to set table
here instead of the string interpolation
@@ -888,21 +889,6 @@ func TestAccGrantOnProcedure(t *testing.T) { | |||
prepareProcedure(dbName, procedureName), | |||
), | |||
}, | |||
{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This test needs to remain. Although it does make no sense semantically, this is something that was supported by the deprecated Hashicorp mysql provider, and has made its way into other modules:
I think the fix for this (as described in that issue), is that we need to introduce a v2 of the mysql_grant
resource, ideally specific to each type (eg. mysql_table_grant
, mysql_procedure_grant
, etc).
Got it. I'm afraid I'm a bit time-constrained right now to be able to implement additional changes, mostly because "it works on my machine"™ I'll close this PR for now and keep following #112 to ensure I jump back to upstream when it's fixed. Thanks a lot for the effort in maintaining it :) |
This fixes the issue described in
#112 where it's
not possible to import some grants. In short, it:
desiredProcedureGrant
, separating it fromdesiredGrant
, which nowbecomes
desiredTableGrant
. This is used when trying to find aconflict and can probably be made a bit more generic, but it's likely
outside the scope of this change (see below)
formatDatabaseName
intoproduceGrantId
which, asthe name says, produced the grant id that is going to be used by the
provider.
most important one being the
id
which was missing and causing theerrors that were seen in the issue above.
It also fixes a typo in the docs that I introduced earlier.
There are a few things worth noting:
that, so there's no good way of testing it properly.
refactored to be more generic. That being said, it would also require
implementing the fixes for role grants to write it in such a
way that it would be properly generic.