Skip to content

Commit 46da779

Browse files
authored
Added databricks_share resource, databricks_shares data source, and databricks_share data source (#1664)
1 parent 21c96e9 commit 46da779

17 files changed

+1210
-15
lines changed

catalog/acceptance/share_test.go

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
package acceptance
2+
3+
import (
4+
"testing"
5+
6+
"github.com/databricks/terraform-provider-databricks/internal/acceptance"
7+
"github.com/databricks/terraform-provider-databricks/qa"
8+
)
9+
10+
func TestUcAccCreateShare(t *testing.T) {
11+
qa.RequireCloudEnv(t, "ucws")
12+
acceptance.Test(t, []acceptance.Step{
13+
{
14+
Template: `
15+
resource "databricks_catalog" "sandbox" {
16+
name = "sandbox{var.RANDOM}"
17+
comment = "this catalog is managed by terraform"
18+
properties = {
19+
purpose = "testing"
20+
}
21+
}
22+
resource "databricks_schema" "things" {
23+
catalog_name = databricks_catalog.sandbox.id
24+
name = "things{var.RANDOM}"
25+
comment = "this database is managed by terraform"
26+
properties = {
27+
kind = "various"
28+
}
29+
}
30+
31+
resource "databricks_table" "mytable" {
32+
catalog_name = databricks_catalog.sandbox.id
33+
schema_name = databricks_schema.things.name
34+
name = "bar"
35+
table_type = "MANAGED"
36+
data_source_format = "DELTA"
37+
38+
column {
39+
name = "id"
40+
position = 0
41+
type_name = "INT"
42+
type_text = "int"
43+
type_json = "{\"name\":\"id\",\"type\":\"integer\",\"nullable\":true,\"metadata\":{}}"
44+
}
45+
}
46+
47+
resource "databricks_share" "myshare" {
48+
name = "{var.RANDOM}-terraform-delta-share"
49+
object {
50+
name = databricks_table.mytable.id
51+
comment = "c"
52+
data_object_type = "TABLE"
53+
}
54+
}
55+
56+
resource "databricks_recipient" "db2open" {
57+
name = "{var.RANDOM}-terraform-db2open-recipient"
58+
comment = "made by terraform"
59+
authentication_type = "TOKEN"
60+
sharing_code = "{var.RANDOM}"
61+
ip_access_list {
62+
// using private ip for acc testing
63+
allowed_ip_addresses = ["10.0.0.0/16"]
64+
}
65+
}
66+
67+
resource "databricks_grants" "some" {
68+
share = databricks_share.myshare.name
69+
grant {
70+
principal = databricks_recipient.db2open.name
71+
privileges = ["SELECT"]
72+
}
73+
}
74+
`,
75+
},
76+
})
77+
}

catalog/data_share.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package catalog
2+
3+
import (
4+
"context"
5+
6+
"github.com/databricks/terraform-provider-databricks/common"
7+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
8+
)
9+
10+
func DataSourceShare() *schema.Resource {
11+
type ShareDetail struct {
12+
Name string `json:"name,omitempty" tf:"computed"`
13+
Objects []SharedDataObject `json:"objects,omitempty" tf:"computed,slice_set,alias:object"`
14+
CreatedAt int64 `json:"created_at,omitempty" tf:"computed"`
15+
CreatedBy string `json:"created_by,omitempty" tf:"computed"`
16+
}
17+
return common.DataResource(ShareDetail{}, func(ctx context.Context, e any, c *common.DatabricksClient) error {
18+
data := e.(*ShareDetail)
19+
sharesAPI := NewSharesAPI(ctx, c)
20+
share, err := sharesAPI.get(data.Name)
21+
if err != nil {
22+
return err
23+
}
24+
data.Objects = share.Objects
25+
data.CreatedAt = share.CreatedAt
26+
data.CreatedBy = share.CreatedBy
27+
return nil
28+
})
29+
}

catalog/data_share_test.go

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
package catalog
2+
3+
import (
4+
"testing"
5+
6+
"github.com/databricks/terraform-provider-databricks/qa"
7+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
8+
"github.com/stretchr/testify/assert"
9+
)
10+
11+
func TestShareData(t *testing.T) {
12+
d, err := qa.ResourceFixture{
13+
Fixtures: []qa.HTTPFixture{
14+
{
15+
Method: "GET",
16+
Resource: "/api/2.1/unity-catalog/shares/a?include_shared_data=true",
17+
Response: ShareInfo{
18+
Name: "a",
19+
Objects: []SharedDataObject{
20+
{
21+
Name: "a",
22+
DataObjectType: "TABLE",
23+
Comment: "c",
24+
SharedAs: "",
25+
AddedAt: 0,
26+
AddedBy: "",
27+
},
28+
},
29+
CreatedBy: "bob",
30+
CreatedAt: 1921321,
31+
},
32+
},
33+
},
34+
Resource: DataSourceShare(),
35+
Read: true,
36+
NonWritable: true,
37+
ID: "_",
38+
HCL: `
39+
name = "a"
40+
`,
41+
}.Apply(t)
42+
assert.NoError(t, err, err)
43+
assert.Equal(t, "bob", d.Get("created_by"))
44+
assert.Equal(t, 1921321, d.Get("created_at"))
45+
assert.Equal(t,
46+
map[string]interface{}{
47+
"added_at": 0,
48+
"added_by": "",
49+
"comment": "c",
50+
"data_object_type": "TABLE",
51+
"name": "a",
52+
"shared_as": "",
53+
},
54+
d.Get("object").(*schema.Set).List()[0])
55+
}
56+
57+
func TestShareData_Error(t *testing.T) {
58+
qa.ResourceFixture{
59+
Fixtures: qa.HTTPFailures,
60+
Resource: DataSourceShare(),
61+
Read: true,
62+
NonWritable: true,
63+
ID: "_",
64+
}.ExpectError(t, "I'm a teapot")
65+
}

catalog/data_shares.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package catalog
2+
3+
import (
4+
"context"
5+
6+
"github.com/databricks/terraform-provider-databricks/common"
7+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
8+
)
9+
10+
func DataSourceShares() *schema.Resource {
11+
type sharesData struct {
12+
Shares []string `json:"shares,omitempty" tf:"computed,slice_set"`
13+
}
14+
return common.DataResource(sharesData{}, func(ctx context.Context, e any, c *common.DatabricksClient) error {
15+
data := e.(*sharesData)
16+
sharesAPI := NewSharesAPI(ctx, c)
17+
shares, err := sharesAPI.list()
18+
if err != nil {
19+
return err
20+
}
21+
for _, share := range shares.Shares {
22+
data.Shares = append(data.Shares, share.Name)
23+
}
24+
return nil
25+
})
26+
}

catalog/data_shares_test.go

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package catalog
2+
3+
import (
4+
"testing"
5+
6+
"github.com/databricks/terraform-provider-databricks/qa"
7+
)
8+
9+
func TestSharesData(t *testing.T) {
10+
qa.ResourceFixture{
11+
Fixtures: []qa.HTTPFixture{
12+
{
13+
Method: "GET",
14+
Resource: "/api/2.1/unity-catalog/shares",
15+
Response: Shares{
16+
Shares: []ShareInfo{
17+
{
18+
Name: "a",
19+
Objects: []SharedDataObject{
20+
{
21+
Name: "a",
22+
DataObjectType: "TABLE",
23+
Comment: "c",
24+
},
25+
},
26+
CreatedAt: 0,
27+
CreatedBy: "",
28+
},
29+
},
30+
},
31+
},
32+
},
33+
Resource: DataSourceShares(),
34+
Read: true,
35+
NonWritable: true,
36+
ID: "_",
37+
}.ApplyNoError(t)
38+
}
39+
40+
func TestSharesData_Error(t *testing.T) {
41+
qa.ResourceFixture{
42+
Fixtures: qa.HTTPFailures,
43+
Resource: DataSourceShares(),
44+
Read: true,
45+
NonWritable: true,
46+
ID: "_",
47+
}.ExpectError(t, "I'm a teapot")
48+
}

catalog/resource_grants.go

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,13 +97,20 @@ func NewPermissionsAPI(ctx context.Context, m any) PermissionsAPI {
9797
return PermissionsAPI{m.(*common.DatabricksClient), context.WithValue(ctx, common.Api, common.API_2_1)}
9898
}
9999

100+
func getPermissionEndpoint(securable, name string) string {
101+
if securable == "share" {
102+
return fmt.Sprintf("/unity-catalog/shares/%s/permissions", name)
103+
}
104+
return fmt.Sprintf("/unity-catalog/permissions/%s/%s", securable, name)
105+
}
106+
100107
func (a PermissionsAPI) getPermissions(securable, name string) (list PermissionsList, err error) {
101-
err = a.client.Get(a.context, fmt.Sprintf("/unity-catalog/permissions/%s/%s", securable, name), nil, &list)
108+
err = a.client.Get(a.context, getPermissionEndpoint(securable, name), nil, &list)
102109
return
103110
}
104111

105112
func (a PermissionsAPI) updatePermissions(securable, name string, diff permissionsDiff) error {
106-
return a.client.Patch(a.context, fmt.Sprintf("/unity-catalog/permissions/%s/%s", securable, name), diff)
113+
return a.client.Patch(a.context, getPermissionEndpoint(securable, name), diff)
107114
}
108115

109116
// replacePermissions merges removal diff of existing permissions on the platform
@@ -237,6 +244,9 @@ var mapping = securableMapping{
237244
"SELECT": true,
238245
"REFRESH": true,
239246
},
247+
"share": {
248+
"SELECT": true,
249+
},
240250
}
241251

242252
func setToStrings(set *schema.Set) (ss []string) {

catalog/resource_grants_test.go

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,3 +240,110 @@ func TestPermissionsList_Diff_LocalRemoteDiff(t *testing.T) {
240240
assert.Equal(t, "a", diff.Changes[0].Add[0])
241241
assert.Equal(t, "c", diff.Changes[0].Remove[0])
242242
}
243+
244+
func TestShareGrantCreate(t *testing.T) {
245+
qa.ResourceFixture{
246+
Fixtures: []qa.HTTPFixture{
247+
{
248+
Method: "GET",
249+
Resource: "/api/2.1/unity-catalog/shares/myshare/permissions",
250+
Response: PermissionsList{
251+
Assignments: []PrivilegeAssignment{},
252+
},
253+
},
254+
{
255+
Method: "PATCH",
256+
Resource: "/api/2.1/unity-catalog/shares/myshare/permissions",
257+
ExpectedRequest: permissionsDiff{
258+
Changes: []permissionsChange{
259+
{
260+
Principal: "me",
261+
Add: []string{"SELECT"},
262+
},
263+
},
264+
},
265+
},
266+
{
267+
Method: "GET",
268+
Resource: "/api/2.1/unity-catalog/shares/myshare/permissions",
269+
Response: PermissionsList{
270+
Assignments: []PrivilegeAssignment{
271+
{
272+
Principal: "me",
273+
Privileges: []string{"SELECT"},
274+
},
275+
},
276+
},
277+
},
278+
},
279+
Resource: ResourceGrants(),
280+
Create: true,
281+
HCL: `
282+
share = "myshare"
283+
284+
grant {
285+
principal = "me"
286+
privileges = ["SELECT"]
287+
}`,
288+
}.ApplyNoError(t)
289+
}
290+
291+
func TestShareGrantUpdate(t *testing.T) {
292+
qa.ResourceFixture{
293+
Fixtures: []qa.HTTPFixture{
294+
{
295+
Method: "GET",
296+
Resource: "/api/2.1/unity-catalog/shares/myshare/permissions",
297+
Response: PermissionsList{
298+
Assignments: []PrivilegeAssignment{
299+
{
300+
Principal: "me",
301+
Privileges: []string{"SELECT"},
302+
},
303+
},
304+
},
305+
},
306+
{
307+
Method: "PATCH",
308+
Resource: "/api/2.1/unity-catalog/shares/myshare/permissions",
309+
ExpectedRequest: permissionsDiff{
310+
Changes: []permissionsChange{
311+
{
312+
Principal: "me",
313+
Remove: []string{"SELECT"},
314+
},
315+
{
316+
Principal: "you",
317+
Add: []string{"SELECT"},
318+
},
319+
},
320+
},
321+
},
322+
{
323+
Method: "GET",
324+
Resource: "/api/2.1/unity-catalog/shares/myshare/permissions",
325+
Response: PermissionsList{
326+
Assignments: []PrivilegeAssignment{
327+
{
328+
Principal: "you",
329+
Privileges: []string{"SELECT"},
330+
},
331+
},
332+
},
333+
},
334+
},
335+
Resource: ResourceGrants(),
336+
Update: true,
337+
ID: "share/myshare",
338+
InstanceState: map[string]string{
339+
"share": "myshare",
340+
},
341+
HCL: `
342+
share = "myshare"
343+
344+
grant {
345+
principal = "you"
346+
privileges = ["SELECT"]
347+
}`,
348+
}.ApplyNoError(t)
349+
}

0 commit comments

Comments
 (0)