Skip to content

Commit 605abe2

Browse files
committed
[Exporter] Improve handling of owner for UC resources
Changes includes emitting of `owner` for UC resources and handling dependencies to corresponding users/sps/groups.
1 parent 41317f3 commit 605abe2

File tree

3 files changed

+96
-20
lines changed

3 files changed

+96
-20
lines changed

NEXT_CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
* Correctly handle account-level identities when generating the code ([#4650](https://github.com/databricks/terraform-provider-databricks/pull/4650))
2121
* Add export of dashboard tasks in `datarbicks_job` ([#4665](https://github.com/databricks/terraform-provider-databricks/pull/4665))
22-
* Add `Ignore` implementation for `databricks_grants` to fix issue with wrongly generated dependencies ([#4661](https://github.com/databricks/terraform-provider-databricks/pull/4650))
22+
* Add `Ignore` implementation for `databricks_grants` to fix issue with wrongly generated dependencies ([#4650](https://github.com/databricks/terraform-provider-databricks/pull/4650))
23+
* Improve handling of `owner` for UC resources ([#4669](https://github.com/databricks/terraform-provider-databricks/pull/4669))
2324

2425
### Internal Changes

exporter/impl_uc.go

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ func listUcCatalogs(ic *importContext) error {
3535
}, v.Name, v.UpdatedAt, fmt.Sprintf("catalog '%s'", v.Name))
3636
}
3737
default:
38+
// TODO: remove this skipping - we need to emit grants for all catalogs, but
39+
// we need to convert these catalog types to data sources
3840
log.Printf("[INFO] Skipping catalog %s of type %s", v.Name, v.CatalogType)
3941
}
4042
}
@@ -46,13 +48,13 @@ func importUcCatalog(ic *importContext, r *resource) error {
4648
s := ic.Resources["databricks_catalog"].Schema
4749
common.DataToStructPointer(r.Data, s, &cat)
4850

51+
// TODO: convert `main` catalog into the data source as it's automatically created?
4952
// Emit: UC Connection, List schemas, Catalog grants, ...
5053
owner, catalogGrantsResource := ic.emitUCGrantsWithOwner("catalog/"+cat.Name, r)
5154
dependsOn := []*resource{}
5255
if owner != "" && owner != ic.meUserName {
5356
dependsOn = append(dependsOn, catalogGrantsResource)
5457
}
55-
// TODO: emit owner? Should we do this? Because it's a account-level identity... Create a separate function for that...
5658
if cat.ConnectionName != "" {
5759
ic.Emit(&resource{
5860
Resource: "databricks_connection",
@@ -99,10 +101,6 @@ func importUcSchema(ic *importContext, r *resource) error {
99101
Resource: "databricks_catalog",
100102
ID: catalogName,
101103
})
102-
// r.AddDependsOn(&resource{Resource: "databricks_grants", ID: "catalog/" + catalogName})
103-
104-
// TODO: somehow add depends on catalog's grant...
105-
// TODO: emit owner? See comment in catalog resource
106104
if ic.isServiceInListing("uc-models") {
107105
it := ic.workspaceClient.RegisteredModels.List(ic.Context,
108106
catalog.ListRegisteredModelsRequest{
@@ -200,8 +198,6 @@ func importUcVolume(ic *importContext, r *resource) error {
200198
Resource: "databricks_schema",
201199
ID: schemaFullName,
202200
})
203-
// r.AddDependsOn(&resource{Resource: "databricks_grants", ID: "schema/" + schemaFullName})
204-
// TODO: emit owner? See comment in catalog resource
205201
return nil
206202
}
207203

@@ -334,12 +330,35 @@ func (ic *importContext) emitUCGrantsWithOwner(id string, parentResource *resour
334330
if ok {
335331
gr.AddExtraData("owner", ownerRaw)
336332
owner = ownerRaw.(string)
333+
emitUserSpOrGroup(ic, owner)
337334
}
338335
}
339336
ic.Emit(gr)
340337
return owner, gr
341338
}
342339

340+
func emitUserSpOrGroup(ic *importContext, userOrSOrGroupPName string) {
341+
if common.StringIsUUID(userOrSOrGroupPName) {
342+
ic.Emit(&resource{
343+
Resource: "databricks_service_principal",
344+
Attribute: "application_id",
345+
Value: userOrSOrGroupPName,
346+
})
347+
} else if strings.Contains(userOrSOrGroupPName, "@") {
348+
ic.Emit(&resource{
349+
Resource: "databricks_user",
350+
Attribute: "user_name",
351+
Value: userOrSOrGroupPName,
352+
})
353+
} else {
354+
ic.Emit(&resource{
355+
Resource: "databricks_group",
356+
Attribute: "display_name",
357+
Value: userOrSOrGroupPName,
358+
})
359+
}
360+
}
361+
343362
func shouldOmitForUnityCatalog(ic *importContext, pathString string, as *schema.Schema, d *schema.ResourceData) bool {
344363
if pathString == "owner" {
345364
return d.Get(pathString).(string) == ""
@@ -498,7 +517,6 @@ func listUcMetastores(ic *importContext) error {
498517

499518
func importUcMetastores(ic *importContext, r *resource) error {
500519
ic.emitUCGrantsWithOwner("metastore/"+r.ID, r)
501-
// TODO: emit owner? See comment in catalog resource
502520
if ic.accountLevel {
503521
// emit metastore assignments
504522
assignments, err := ic.accountClient.MetastoreAssignments.ListByMetastoreId(ic.Context, r.ID)
@@ -615,7 +633,5 @@ func importSqlTable(ic *importContext, r *resource) error {
615633
Resource: "databricks_schema",
616634
ID: schemaFullName,
617635
})
618-
// r.AddDependsOn(&resource{Resource: "databricks_grants", ID: "schema/" + schemaFullName})
619-
// TODO: emit owner? See comment in catalog resource
620636
return nil
621637
}

exporter/importables.go

Lines changed: 68 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2055,13 +2055,20 @@ var resourcesMap map[string]importable = map[string]importable{
20552055
}
20562056
return shouldOmitForUnityCatalog(ic, pathString, as, d)
20572057
},
2058-
Ignore: generateIgnoreObjectWithEmptyAttributeValue("databricks_catalog", "name"),
2058+
Ignore: func(ic *importContext, r *resource) bool {
2059+
res := (r.Data != nil && (r.Data.Get("name").(string) == "" || r.Data.Get("name").(string) == "system"))
2060+
if res {
2061+
ic.addIgnoredResource(fmt.Sprintf("databricks_catalog. id=%s", r.ID))
2062+
}
2063+
return res
2064+
},
20592065
Depends: []reference{
20602066
{Path: "connection_name", Resource: "databricks_connection", Match: "name"},
20612067
{Path: "storage_root", Resource: "databricks_external_location", Match: "url", MatchType: MatchLongestPrefix},
2068+
{Path: "owner", Resource: "databricks_service_principal", Match: "application_id"},
2069+
{Path: "owner", Resource: "databricks_group", Match: "display_name"},
2070+
{Path: "owner", Resource: "databricks_user", Match: "user_name", MatchType: MatchCaseInsensitive},
20622071
},
2063-
// TODO: convert `main` catalog into the data source as it's automatically created?
2064-
// This will require addition of the databricks_catalog data source
20652072
},
20662073
"databricks_schema": {
20672074
WorkspaceLevel: true,
@@ -2072,6 +2079,9 @@ var resourcesMap map[string]importable = map[string]importable{
20722079
Depends: []reference{
20732080
{Path: "catalog_name", Resource: "databricks_catalog"},
20742081
{Path: "storage_root", Resource: "databricks_external_location", Match: "url", MatchType: MatchLongestPrefix},
2082+
{Path: "owner", Resource: "databricks_service_principal", Match: "application_id"},
2083+
{Path: "owner", Resource: "databricks_group", Match: "display_name"},
2084+
{Path: "owner", Resource: "databricks_user", Match: "user_name", MatchType: MatchCaseInsensitive},
20752085
},
20762086
},
20772087
"databricks_volume": {
@@ -2092,6 +2102,9 @@ var resourcesMap map[string]importable = map[string]importable{
20922102
SkipDirectLookup: true},
20932103
{Path: "storage_location", Resource: "databricks_external_location",
20942104
Match: "url", MatchType: MatchLongestPrefix},
2105+
{Path: "owner", Resource: "databricks_service_principal", Match: "application_id"},
2106+
{Path: "owner", Resource: "databricks_group", Match: "display_name"},
2107+
{Path: "owner", Resource: "databricks_user", Match: "user_name", MatchType: MatchCaseInsensitive},
20952108
},
20962109
},
20972110
"databricks_sql_table": {
@@ -2116,6 +2129,9 @@ var resourcesMap map[string]importable = map[string]importable{
21162129
SkipDirectLookup: true},
21172130
{Path: "storage_location", Resource: "databricks_external_location",
21182131
Match: "url", MatchType: MatchLongestPrefix},
2132+
{Path: "owner", Resource: "databricks_service_principal", Match: "application_id"},
2133+
{Path: "owner", Resource: "databricks_group", Match: "display_name"},
2134+
{Path: "owner", Resource: "databricks_user", Match: "user_name", MatchType: MatchCaseInsensitive},
21192135
},
21202136
},
21212137
"databricks_grants": {
@@ -2152,6 +2168,9 @@ var resourcesMap map[string]importable = map[string]importable{
21522168
ShouldOmitField: shouldOmitWithIsolationMode,
21532169
Depends: []reference{
21542170
{Path: "azure_service_principal.client_secret", Variable: true},
2171+
{Path: "owner", Resource: "databricks_service_principal", Match: "application_id"},
2172+
{Path: "owner", Resource: "databricks_group", Match: "display_name"},
2173+
{Path: "owner", Resource: "databricks_user", Match: "user_name", MatchType: MatchCaseInsensitive},
21552174
},
21562175
},
21572176
"databricks_credential": {
@@ -2162,6 +2181,9 @@ var resourcesMap map[string]importable = map[string]importable{
21622181
ShouldOmitField: shouldOmitWithIsolationMode,
21632182
Depends: []reference{
21642183
{Path: "azure_service_principal.client_secret", Variable: true},
2184+
{Path: "owner", Resource: "databricks_service_principal", Match: "application_id"},
2185+
{Path: "owner", Resource: "databricks_group", Match: "display_name"},
2186+
{Path: "owner", Resource: "databricks_user", Match: "user_name", MatchType: MatchCaseInsensitive},
21652187
},
21662188
},
21672189
"databricks_external_location": {
@@ -2184,6 +2206,9 @@ var resourcesMap map[string]importable = map[string]importable{
21842206
},
21852207
Depends: []reference{
21862208
{Path: "credential_name", Resource: "databricks_storage_credential", Match: "name"},
2209+
{Path: "owner", Resource: "databricks_service_principal", Match: "application_id"},
2210+
{Path: "owner", Resource: "databricks_group", Match: "display_name"},
2211+
{Path: "owner", Resource: "databricks_user", Match: "user_name", MatchType: MatchCaseInsensitive},
21872212
},
21882213
},
21892214
"databricks_connection": {
@@ -2200,12 +2225,25 @@ var resourcesMap map[string]importable = map[string]importable{
22002225
List: listUcConnections,
22012226
// TODO: think what to do with the sensitive fields in the `options`?
22022227
Import: func(ic *importContext, r *resource) error {
2203-
// TODO: do we need to emit the owner See comment for the owner...
22042228
connectionName := r.Data.Get("name").(string)
22052229
ic.emitUCGrantsWithOwner("foreign_connection/"+connectionName, r)
22062230
return nil
22072231
},
2232+
Ignore: func(ic *importContext, r *resource) bool {
2233+
res := (r.Data.Get("connection_type").(string) == "ONLINE_CATALOG" &&
2234+
strings.HasPrefix(r.Data.Get("name").(string), "internal-") &&
2235+
r.Data.Get("owner").(string) == "System user")
2236+
if res {
2237+
ic.addIgnoredResource(fmt.Sprintf("databricks_connection. id=%s", r.ID))
2238+
}
2239+
return res
2240+
},
22082241
ShouldOmitField: shouldOmitForUnityCatalog,
2242+
Depends: []reference{
2243+
{Path: "owner", Resource: "databricks_service_principal", Match: "application_id"},
2244+
{Path: "owner", Resource: "databricks_group", Match: "display_name"},
2245+
{Path: "owner", Resource: "databricks_user", Match: "user_name", MatchType: MatchCaseInsensitive},
2246+
},
22092247
},
22102248
"databricks_share": {
22112249
WorkspaceLevel: true,
@@ -2225,7 +2263,6 @@ var resourcesMap map[string]importable = map[string]importable{
22252263
return nil
22262264
},
22272265
Import: func(ic *importContext, r *resource) error {
2228-
// TODO: do we need to emit the owner See comment for the owner...
22292266
var share tf_sharing.ShareInfo
22302267
s := ic.Resources["databricks_share"].Schema
22312268
common.DataToStructPointer(r.Data, s, &share)
@@ -2262,6 +2299,9 @@ var resourcesMap map[string]importable = map[string]importable{
22622299
{Path: "object.name", Resource: "databricks_registered_model", IsValidApproximation: isMatchignShareObject("MODEL")},
22632300
{Path: "object.name", Resource: "databricks_schema", IsValidApproximation: isMatchignShareObject("SCHEMA")},
22642301
{Path: "object.name", Resource: "databricks_sql_table", IsValidApproximation: isMatchignShareObject("TABLE")},
2302+
{Path: "owner", Resource: "databricks_service_principal", Match: "application_id"},
2303+
{Path: "owner", Resource: "databricks_group", Match: "display_name"},
2304+
{Path: "owner", Resource: "databricks_user", Match: "user_name", MatchType: MatchCaseInsensitive},
22652305
},
22662306
},
22672307
"databricks_recipient": {
@@ -2281,7 +2321,18 @@ var resourcesMap map[string]importable = map[string]importable{
22812321
}
22822322
return nil
22832323
},
2284-
// TODO: do we need to emit the owner See comment for the owner...
2324+
Import: func(ic *importContext, r *resource) error {
2325+
owner := r.Data.Get("owner").(string)
2326+
if owner != "" {
2327+
emitUserSpOrGroup(ic, owner)
2328+
}
2329+
return nil
2330+
},
2331+
Depends: []reference{
2332+
{Path: "owner", Resource: "databricks_service_principal", Match: "application_id"},
2333+
{Path: "owner", Resource: "databricks_group", Match: "display_name"},
2334+
{Path: "owner", Resource: "databricks_user", Match: "user_name", MatchType: MatchCaseInsensitive},
2335+
},
22852336
// TODO: emit variable for sharing_code ...
22862337
// TODO: add depends for sharing_code?
22872338
},
@@ -2311,8 +2362,6 @@ var resourcesMap map[string]importable = map[string]importable{
23112362
Resource: "databricks_schema",
23122363
ID: schemaFullName,
23132364
})
2314-
// r.AddDependsOn(&resource{Resource: "databricks_grants", ID: "schema/" + schemaFullName})
2315-
// TODO: emit owner? See comment in catalog resource
23162365
return nil
23172366
},
23182367
ShouldOmitField: func(ic *importContext, pathString string, as *schema.Schema, d *schema.ResourceData) bool {
@@ -2332,6 +2381,9 @@ var resourcesMap map[string]importable = map[string]importable{
23322381
IsValidApproximation: createIsMatchingCatalogAndSchema("catalog_name", "schema_name"),
23332382
SkipDirectLookup: true},
23342383
{Path: "storage_root", Resource: "databricks_external_location", Match: "url", MatchType: MatchLongestPrefix},
2384+
{Path: "owner", Resource: "databricks_service_principal", Match: "application_id"},
2385+
{Path: "owner", Resource: "databricks_group", Match: "display_name"},
2386+
{Path: "owner", Resource: "databricks_user", Match: "user_name", MatchType: MatchCaseInsensitive},
23352387
},
23362388
},
23372389
"databricks_metastore": {
@@ -2347,6 +2399,11 @@ var resourcesMap map[string]importable = map[string]importable{
23472399
}
23482400
return shouldOmitForUnityCatalog(ic, pathString, as, d)
23492401
},
2402+
Depends: []reference{
2403+
{Path: "owner", Resource: "databricks_service_principal", Match: "application_id"},
2404+
{Path: "owner", Resource: "databricks_group", Match: "display_name"},
2405+
{Path: "owner", Resource: "databricks_user", Match: "user_name", MatchType: MatchCaseInsensitive},
2406+
},
23502407
},
23512408
"databricks_metastore_assignment": {
23522409
AccountLevel: true,
@@ -2602,7 +2659,6 @@ var resourcesMap map[string]importable = map[string]importable{
26022659
Resource: "databricks_sql_table",
26032660
ID: r.Data.Get("spec.0.source_table_full_name").(string),
26042661
})
2605-
// TODO: emit owner? See comment in catalog resource
26062662
return nil
26072663
},
26082664
Ignore: generateIgnoreObjectWithEmptyAttributeValue("databricks_online_table", "name"),
@@ -2613,6 +2669,9 @@ var resourcesMap map[string]importable = map[string]importable{
26132669
IsValidApproximation: createIsMatchingCatalogAndSchema("catalog_name", "schema_name"),
26142670
SkipDirectLookup: true},
26152671
{Path: "spec.source_table_full_name", Resource: "databricks_sql_table"},
2672+
{Path: "owner", Resource: "databricks_service_principal", Match: "application_id"},
2673+
{Path: "owner", Resource: "databricks_group", Match: "display_name"},
2674+
{Path: "owner", Resource: "databricks_user", Match: "user_name", MatchType: MatchCaseInsensitive},
26162675
},
26172676
},
26182677
"databricks_vector_search_endpoint": {

0 commit comments

Comments
 (0)