-
Notifications
You must be signed in to change notification settings - Fork 361
/
permissions.go
146 lines (129 loc) · 4.57 KB
/
permissions.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
package permissions
import (
"context"
"fmt"
"log"
"time"
"github.com/databricks/databricks-sdk-go"
"github.com/databricks/databricks-sdk-go/service/catalog"
"github.com/databricks/databricks-sdk-go/service/sharing"
"github.com/databricks/terraform-provider-databricks/common"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)
// API
type UnityCatalogPermissionsAPI struct {
client *databricks.WorkspaceClient
context context.Context
}
func NewUnityCatalogPermissionsAPI(ctx context.Context, m any) UnityCatalogPermissionsAPI {
client, _ := m.(*common.DatabricksClient).WorkspaceClient()
return UnityCatalogPermissionsAPI{client, ctx}
}
func (a UnityCatalogPermissionsAPI) GetPermissions(securable catalog.SecurableType, name string) (list *catalog.PermissionsList, err error) {
if securable.String() == "share" {
list, err = a.client.Shares.SharePermissions(a.context, sharing.SharePermissionsRequest{name})
return
}
list, err = a.client.Grants.GetBySecurableTypeAndFullName(a.context, securable, name)
return
}
func (a UnityCatalogPermissionsAPI) UpdatePermissions(securable catalog.SecurableType, name string, diff []catalog.PermissionsChange) error {
if securable.String() == "share" {
return a.client.Shares.UpdatePermissions(a.context, sharing.UpdateSharePermissions{
Changes: diff,
Name: name,
})
}
_, err := a.client.Grants.Update(a.context, catalog.UpdatePermissions{
Changes: diff,
SecurableType: securable,
FullName: name,
})
return err
}
func (a UnityCatalogPermissionsAPI) WaitForUpdate(timeout time.Duration, securable catalog.SecurableType, name string, desired catalog.PermissionsList, diff func(*catalog.PermissionsList, catalog.PermissionsList) []catalog.PermissionsChange) error {
return retry.RetryContext(a.context, timeout, func() *retry.RetryError {
current, err := a.GetPermissions(securable, name)
if err != nil {
return retry.NonRetryableError(err)
}
log.Printf("[DEBUG] Permissions for %s-%s are: %v", securable.String(), name, current)
if diff(current, desired) == nil {
return nil
}
return retry.RetryableError(
fmt.Errorf("permissions for %s-%s are %v, but have to be %v", securable.String(), name, current, desired),
)
})
}
// Terraform Schema
type UnityCatalogPrivilegeAssignment struct {
Principal string `json:"principal"`
Privileges []string `json:"privileges" tf:"slice_set"`
}
// Permission Mappings
type SecurableMapping map[string]catalog.SecurableType
// reuse ResourceDiff and ResourceData
type attributeGetter interface {
Get(key string) any
}
func (sm SecurableMapping) GetSecurableType(securable string) catalog.SecurableType {
return sm[securable]
}
func (sm SecurableMapping) KeyValue(d attributeGetter) (string, string) {
for field := range sm {
v := d.Get(field).(string)
if v == "" {
continue
}
return field, v
}
log.Printf("[WARN] Unexpected resource or permissions. Please proceed at your own risk.")
return "unknown", "unknown"
}
func (sm SecurableMapping) Id(d *schema.ResourceData) string {
securable, name := sm.KeyValue(d)
return fmt.Sprintf("%s/%s", securable, name)
}
// Mappings
// See https://docs.databricks.com/api/workspace/grants/update for full list
// Omitting provider as a reserved keyword
var Mappings = SecurableMapping{
"catalog": catalog.SecurableType("catalog"),
"foreign_connection": catalog.SecurableType("connection"),
"external_location": catalog.SecurableType("external_location"),
"function": catalog.SecurableType("function"),
"metastore": catalog.SecurableType("metastore"),
"model": catalog.SecurableType("function"),
"pipeline": catalog.SecurableType("pipeline"),
"recipient": catalog.SecurableType("recipient"),
"schema": catalog.SecurableType("schema"),
"share": catalog.SecurableType("share"),
"storage_credential": catalog.SecurableType("storage_credential"),
"table": catalog.SecurableType("table"),
"volume": catalog.SecurableType("volume"),
}
// Utils for Slice and Set
func SliceToSet(in []catalog.Privilege) *schema.Set {
var out []any
for _, v := range in {
out = append(out, v.String())
}
return schema.NewSet(schema.HashString, out)
}
func SetToSlice(set *schema.Set) (ss []catalog.Privilege) {
for _, v := range set.List() {
ss = append(ss, catalog.Privilege(v.(string)))
}
return
}
func SliceWithoutString(in []string, without string) (out []string) {
for _, v := range in {
if v == without {
continue
}
out = append(out, v)
}
return
}