-
Notifications
You must be signed in to change notification settings - Fork 394
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
[Internal] Migrate Share Resource to Plugin Framework #4047
[Internal] Migrate Share Resource to Plugin Framework #4047
Conversation
9beb175
to
7a25dfd
Compare
37824e8
to
772f102
Compare
c0ef184
to
92d9927
Compare
92d9927
to
81769af
Compare
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.
No major concerns about the business logic (though I'm probably not the best person to review it). I left a few nit comments about style.
_, exists := afterMap[beforeSdo.Name] | ||
if exists { |
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.
[nit] inline to make it clear that exists
is not used outside of the condition. Also, it is more idiomatic to call such variable ok
:
_, exists := afterMap[beforeSdo.Name] | |
if exists { | |
if _, ok := afterMap[beforeSdo.Name]; ok { |
beforeSdo, exists := beforeMap[afterSdo.Name] | ||
if exists { |
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.
Ditto
beforeSdo, exists := beforeMap[afterSdo.Name] | |
if exists { | |
if beforeSdo, ok := beforeMap[afterSdo.Name]; ok { |
changes = append(changes, sharing.SharedDataObjectUpdate{ | ||
Action: sharing.SharedDataObjectUpdateAction(action), | ||
DataObject: &obj, | ||
}, | ||
) |
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.
Curious, did this pass gofmt
?
changes = append(changes, sharing.SharedDataObjectUpdate{ | |
Action: sharing.SharedDataObjectUpdateAction(action), | |
DataObject: &obj, | |
}, | |
) | |
changes = append(changes, sharing.SharedDataObjectUpdate{ | |
Action: sharing.SharedDataObjectUpdateAction(action), | |
DataObject: &obj, | |
}) |
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.
with flying colors 🌈
if len(changes) > 0 { | ||
// if there are any other changes, update the share with the changes | ||
updatedShareInfo, err := client.Shares.Update(ctx, sharing.UpdateShare{ | ||
Name: plan.Name.ValueString(), | ||
Updates: changes, | ||
}) | ||
if err == nil { | ||
resp.Diagnostics.Append(converters.GoSdkToTfSdkStruct(ctx, updatedShareInfo, &state)...) | ||
if resp.Diagnostics.HasError() { | ||
return | ||
} | ||
} else { | ||
rollbackShareInfo, rollbackErr := client.Shares.Update(ctx, sharing.UpdateShare{ | ||
Name: currentShareInfo.Name, | ||
Owner: currentShareInfo.Owner, | ||
}) | ||
if rollbackErr == nil { | ||
resp.Diagnostics.Append(converters.GoSdkToTfSdkStruct(ctx, rollbackShareInfo, &state)...) | ||
if resp.Diagnostics.HasError() { | ||
return | ||
} | ||
} else { | ||
resp.Diagnostics.AddError("failed to roll back", common.OwnerRollbackError(err, rollbackErr, currentShareInfo.Owner, plan.Owner.ValueString()).Error()) | ||
} | ||
|
||
resp.Diagnostics.AddError("failed to update share", err.Error()) | ||
return | ||
} | ||
} |
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.
[nit] We can be a little more idiomatic here by only having the error flow at the highest level of indentation.
Ref: https://go.dev/wiki/CodeReviewComments#indent-error-flow
if len(changes) > 0 { | |
// if there are any other changes, update the share with the changes | |
updatedShareInfo, err := client.Shares.Update(ctx, sharing.UpdateShare{ | |
Name: plan.Name.ValueString(), | |
Updates: changes, | |
}) | |
if err == nil { | |
resp.Diagnostics.Append(converters.GoSdkToTfSdkStruct(ctx, updatedShareInfo, &state)...) | |
if resp.Diagnostics.HasError() { | |
return | |
} | |
} else { | |
rollbackShareInfo, rollbackErr := client.Shares.Update(ctx, sharing.UpdateShare{ | |
Name: currentShareInfo.Name, | |
Owner: currentShareInfo.Owner, | |
}) | |
if rollbackErr == nil { | |
resp.Diagnostics.Append(converters.GoSdkToTfSdkStruct(ctx, rollbackShareInfo, &state)...) | |
if resp.Diagnostics.HasError() { | |
return | |
} | |
} else { | |
resp.Diagnostics.AddError("failed to roll back", common.OwnerRollbackError(err, rollbackErr, currentShareInfo.Owner, plan.Owner.ValueString()).Error()) | |
} | |
resp.Diagnostics.AddError("failed to update share", err.Error()) | |
return | |
} | |
} | |
if len(changes) > 0 { | |
// if there are any other changes, update the share with the changes | |
updatedShareInfo, err := client.Shares.Update(ctx, sharing.UpdateShare{ | |
Name: plan.Name.ValueString(), | |
Updates: changes, | |
}) | |
if err != nil { | |
rollbackShareInfo, rollbackErr := client.Shares.Update(ctx, sharing.UpdateShare{ | |
Name: currentShareInfo.Name, | |
Owner: currentShareInfo.Owner, | |
}) | |
if rollbackErr == nil { | |
resp.Diagnostics.Append(converters.GoSdkToTfSdkStruct(ctx, rollbackShareInfo, &state)...) | |
if resp.Diagnostics.HasError() { | |
return | |
} | |
} else { | |
resp.Diagnostics.AddError("failed to roll back", common.OwnerRollbackError(err, rollbackErr, currentShareInfo.Owner, plan.Owner.ValueString()).Error()) | |
} | |
resp.Diagnostics.AddError("failed to update share", err.Error()) | |
return | |
} | |
resp.Diagnostics.Append(converters.GoSdkToTfSdkStruct(ctx, updatedShareInfo, &state)...) | |
if resp.Diagnostics.HasError() { | |
return | |
} | |
} |
resp.Diagnostics.AddError("failed to roll back", common.OwnerRollbackError(err, rollbackErr, currentShareInfo.Owner, plan.Owner.ValueString()).Error()) | ||
} | ||
|
||
resp.Diagnostics.AddError("failed to update share", err.Error()) |
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.
[nit] Can the last line resp.Diagnostics.AddError("failed to update share", err.Error())
come at the beginning of this else
block? If so, we can make the code more readable by reducing the overall level of indentation.
Ref: https://go.dev/wiki/CodeReviewComments#indent-error-flow
resp.Diagnostics.AddError("failed to update share", err.Error())
rollbackShareInfo, rollbackErr := client.Shares.Update(ctx, sharing.UpdateShare{
Name: currentShareInfo.Name,
Owner: currentShareInfo.Owner,
})
if rollbackErr != nil {
resp.Diagnostics.AddError("failed to roll back", common.OwnerRollbackError(err, rollbackErr, currentShareInfo.Owner, plan.Owner.ValueString()).Error())
return
}
resp.Diagnostics.Append(converters.GoSdkToTfSdkStruct(ctx, rollbackShareInfo, &state)...)
if resp.Diagnostics.HasError() {
return
}
Thanks @renaudhartert-db for the review! Most of the issues are inherited from the migrated code, but no reason not to tidy up now :) Appreciate the comments. |
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.
Thanks for the PR, I had some comments, rest LGTM, stamping to unblock merge once addressed.
}`, owner, comment) | ||
} | ||
|
||
func TestUcAccUpdateShare(t *testing.T) { |
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.
Can you please add an integration test which adds an object in middle in the update step? This was a limitation in SDKv2 as ordering used to matter whereas now it should work with plugin framework.
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 think this would fail currently because object in ShareInfo that we use for schema is a list and it should be set instead.
type ShareInfoExtended struct {
sharing_tf.ShareInfo
}
....
Objects []SharedDataObject `tfsdk:"object" tf:"optional"`
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.
Good catch! Added support + integration test in 4b7eb0e
sharing_tf.ShareInfo | ||
} | ||
|
||
func matchOrder[T any, K comparable](target, reference []T, keyFunc func(T) K) { |
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.
Having this covered with unit test might be good.
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'm not entirely sure. Testing this on a unit level feels like testing implementation details. If this element becomes reusable across different resources, which could happen soon, I'd be more inclined to test it at a unit level. Right now, it seems like we might tweak the implementation as we figure out how to scale this method (like switching to sets). So, unit tests might end up breaking for reasons that aren't really important, like when we refactor the code. We can definitely revisit this and consider unit tests if we start reusing the code and it makes sense to treat it as its own unit.
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.
sounds good 👍
if err != nil { | ||
// delete orphaned share if update fails | ||
if d_err := w.Shares.DeleteByName(ctx, shareInfo.Name); d_err != nil { | ||
resp.Diagnostics.AddError("failed to delete orphaned share", d_err.Error()) |
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.
We should also add err along with d_err in the diagnostics here as we return so line 205 won't execute.
} | ||
|
||
func (r *ShareResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) { | ||
logger.SetTfLogger(logger.NewTfLogger(ctx)) |
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 think we should do this while we configure the client so it gets set for each CRUD in all resources like we do in sdkv2 :https://github.com/databricks/terraform-provider-databricks/blob/main/internal/providers/sdkv2/sdkv2.go#L235.
It doesn't have to be in this PR so we can remove this and create a ticket to track adding this properly.
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.
Heh, no this is just sloppy leftovers from debugging. Oops!
} | ||
|
||
func (r *ShareResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) { | ||
w, diags := r.Client.GetWorkspaceClient() |
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.
Also need to add
ctx = pluginfwcontext.SetUserAgentInResourceContext(ctx, resourceName)
in each CRUD, ref: https://github.com/databricks/terraform-provider-databricks/blob/main/internal/providers/pluginfw/resources/qualitymonitor/resource_quality_monitor.go#L101
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.
👍 e350013
} | ||
} | ||
|
||
state.SyncEffectiveFieldsDuringCreateOrUpdate(plan.ShareInfo) |
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.
Is there an easy way to test this? Also is this something we do this right after update/create is called? i.e. line 328
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 think we might need to use set instead of list here: https://github.com/databricks/terraform-provider-databricks/pull/4047/files#r1806166473.
2efc446
to
4b7eb0e
Compare
e350013
to
52c62e3
Compare
Test Details: go/deco-tests/11569951828 |
### New Features and Improvements * Added `databricks_functions` data source ([#4154](#4154)). ### Bug Fixes * Handle edge case for `effective_properties` in `databricks_sql_table` ([#4153](#4153)). * Provide more prescriptive error when users fail to create a single node cluster ([#4168](#4168)). ### Internal Changes * Add test instructions for external contributors ([#4169](#4169)). * Always write message for manual test integration ([#4188](#4188)). * Make `Read` after `Create`/`Update` configurable ([#4190](#4190)). * Migrate Share Data Source to Plugin Framework ([#4161](#4161)). * Migrate Share Resource to Plugin Framework ([#4047](#4047)). * Rollout Plugin Framework ([#4134](#4134)). ### Dependency Updates * Bump Go SDK to v0.50.0 ([#4178](#4178)). ### Exporter * Allow to match resource names by regular expression ([#4177](#4177)).
### New Features and Improvements * Added `databricks_functions` data source ([#4154](#4154)). ### Bug Fixes * Handle edge case for `effective_properties` in `databricks_sql_table` ([#4153](#4153)). * Provide more prescriptive error when users fail to create a single node cluster ([#4168](#4168)). ### Internal Changes * Add test instructions for external contributors ([#4169](#4169)). * Always write message for manual test integration ([#4188](#4188)). * Make `Read` after `Create`/`Update` configurable ([#4190](#4190)). * Migrate Share Data Source to Plugin Framework ([#4161](#4161)). * Migrate Share Resource to Plugin Framework ([#4047](#4047)). * Rollout Plugin Framework ([#4134](#4134)). ### Dependency Updates * Bump Go SDK to v0.50.0 ([#4178](#4178)). ### Exporter * Allow to match resource names by regular expression ([#4177](#4177)).
Changes
This PR migrates the share resource to the Plugin framework. The code was largely copied "as is" from the previous implementation of the share resource, with the necessary adaptations made for integration with the Plugin framework.
This implementation utilizes the newly generated Effective fields to provide the functionality that was previously achieved through diff suppression.
Tests
make test
run locallydocs/
folderinternal/acceptance