Skip to content

Commit 3614642

Browse files
authored
Feature - Groups (#60)
1 parent 86c8928 commit 3614642

File tree

11 files changed

+587
-2
lines changed

11 files changed

+587
-2
lines changed

VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
0.0.85
1+
0.0.86
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
---
2+
# generated by https://github.com/hashicorp/terraform-plugin-docs
3+
page_title: "dbt_cloud_group Data Source - terraform-provider-dbt-cloud"
4+
subcategory: ""
5+
description: |-
6+
7+
---
8+
9+
# dbt_cloud_group (Data Source)
10+
11+
12+
13+
14+
15+
<!-- schema generated by tfplugindocs -->
16+
## Schema
17+
18+
### Required
19+
20+
- `group_id` (Number) ID of the group
21+
22+
### Read-Only
23+
24+
- `assign_by_default` (Boolean) Whether or not to assign this group to users by default
25+
- `id` (String) The ID of this resource.
26+
- `is_active` (Boolean) Whether the group is active
27+
- `name` (String) Group name
28+
- `sso_mapping_groups` (List of String) SSO mapping group names for this group
29+
30+

docs/resources/dbt_cloud_group.md

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
---
2+
# generated by https://github.com/hashicorp/terraform-plugin-docs
3+
page_title: "dbt_cloud_group Resource - terraform-provider-dbt-cloud"
4+
subcategory: ""
5+
description: |-
6+
7+
---
8+
9+
# dbt_cloud_group (Resource)
10+
11+
12+
13+
14+
15+
<!-- schema generated by tfplugindocs -->
16+
## Schema
17+
18+
### Required
19+
20+
- `name` (String) Group name
21+
22+
### Optional
23+
24+
- `assign_by_default` (Boolean) Whether or not to assign this group to users by default
25+
- `is_active` (Boolean) Whether the group is active
26+
- `sso_mapping_groups` (List of String) SSO mapping group names for this group
27+
28+
### Read-Only
29+
30+
- `id` (String) The ID of this resource.
31+
32+

pkg/data_sources/group.go

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
package data_sources
2+
3+
import (
4+
"context"
5+
"strconv"
6+
7+
"github.com/gthesheep/terraform-provider-dbt-cloud/pkg/dbt_cloud"
8+
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
9+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
10+
)
11+
12+
var groupSchema = map[string]*schema.Schema{
13+
"group_id": &schema.Schema{
14+
Type: schema.TypeInt,
15+
Required: true,
16+
Description: "ID of the group",
17+
},
18+
"is_active": &schema.Schema{
19+
Type: schema.TypeBool,
20+
Computed: true,
21+
Description: "Whether the group is active",
22+
},
23+
"name": &schema.Schema{
24+
Type: schema.TypeString,
25+
Computed: true,
26+
Description: "Group name",
27+
},
28+
"assign_by_default": &schema.Schema{
29+
Type: schema.TypeBool,
30+
Computed: true,
31+
Description: "Whether or not to assign this group to users by default",
32+
},
33+
"sso_mapping_groups": &schema.Schema{
34+
Type: schema.TypeList,
35+
Computed: true,
36+
Description: "SSO mapping group names for this group",
37+
Elem: &schema.Schema{
38+
Type: schema.TypeString,
39+
},
40+
},
41+
}
42+
43+
func DatasourceGroup() *schema.Resource {
44+
return &schema.Resource{
45+
ReadContext: datasourceGroupRead,
46+
Schema: groupSchema,
47+
}
48+
}
49+
50+
func datasourceGroupRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
51+
c := m.(*dbt_cloud.Client)
52+
53+
var diags diag.Diagnostics
54+
55+
groupID := d.Get("group_id").(int)
56+
57+
group, err := c.GetGroup(groupID)
58+
if err != nil {
59+
return diag.FromErr(err)
60+
}
61+
62+
if err := d.Set("is_active", group.State == dbt_cloud.STATE_ACTIVE); err != nil {
63+
return diag.FromErr(err)
64+
}
65+
if err := d.Set("name", group.Name); err != nil {
66+
return diag.FromErr(err)
67+
}
68+
if err := d.Set("assign_by_default", group.AssignByDefault); err != nil {
69+
return diag.FromErr(err)
70+
}
71+
if err := d.Set("sso_mapping_groups", group.SSOMappingGroups); err != nil {
72+
return diag.FromErr(err)
73+
}
74+
75+
d.SetId(strconv.Itoa(*group.ID))
76+
77+
return diags
78+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package data_sources_test
2+
3+
import (
4+
"fmt"
5+
"testing"
6+
7+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest"
8+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
9+
)
10+
11+
func TestAccDbtCloudGroupDataSource(t *testing.T) {
12+
13+
groupName := acctest.RandStringFromCharSet(5, acctest.CharSetAlphaNum)
14+
15+
config := group(groupName)
16+
17+
check := resource.ComposeAggregateTestCheckFunc(
18+
resource.TestCheckResourceAttr("data.dbt_cloud_group.test_group_read", "name", groupName),
19+
resource.TestCheckResourceAttrSet("data.dbt_cloud_group.test_group_read", "is_active"),
20+
resource.TestCheckResourceAttrSet("data.dbt_cloud_group.test_group_read", "assign_by_default"),
21+
)
22+
23+
resource.ParallelTest(t, resource.TestCase{
24+
Providers: providers(),
25+
Steps: []resource.TestStep{
26+
{
27+
Config: config,
28+
Check: check,
29+
},
30+
},
31+
})
32+
}
33+
34+
func group(groupName string) string {
35+
return fmt.Sprintf(`
36+
resource "dbt_cloud_group" "test_group" {
37+
name = "%s"
38+
}
39+
40+
data "dbt_cloud_group" "test_group_read" {
41+
group_id = dbt_cloud_group.test_group.id
42+
}
43+
`, groupName)
44+
}

pkg/dbt_cloud/group.go

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
package dbt_cloud
2+
3+
import (
4+
"encoding/json"
5+
"fmt"
6+
"net/http"
7+
"strconv"
8+
"strings"
9+
)
10+
11+
type GroupPermission struct {
12+
ID *int `json:"id"`
13+
AccountID int `json:"account_id"`
14+
GroupID int `json:"group_id"`
15+
ProjectID int `json:"project_id"`
16+
AllProjects bool `json:"all_projects"`
17+
State int `json:"state"`
18+
Set string `json:"permission_set"`
19+
Level string `json:"permission_level"`
20+
}
21+
22+
type Group struct {
23+
ID *int `json:"id"`
24+
Name string `json:"name"`
25+
AccountID int `json:"account_id"`
26+
State int `json:"state"`
27+
AssignByDefault bool `json:"assign_by_default"`
28+
SSOMappingGroups []string `json:"sso_mapping_groups"`
29+
Permissions []GroupPermission `json:"group_permissions,omitempty"`
30+
}
31+
32+
type GroupResponse struct {
33+
Data Group `json:"data"`
34+
Status ResponseStatus `json:"status"`
35+
}
36+
37+
type GroupListResponse struct {
38+
Data []Group `json:"data"`
39+
Status ResponseStatus `json:"status"`
40+
}
41+
42+
func (c *Client) GetGroup(groupID int) (*Group, error) {
43+
req, err := http.NewRequest("GET", fmt.Sprintf("%s/v3/accounts/%s/groups/", c.HostURL, strconv.Itoa(c.AccountID)), nil)
44+
if err != nil {
45+
return nil, err
46+
}
47+
48+
body, err := c.doRequest(req)
49+
if err != nil {
50+
return nil, err
51+
}
52+
53+
groupListResponse := GroupListResponse{}
54+
err = json.Unmarshal(body, &groupListResponse)
55+
if err != nil {
56+
return nil, err
57+
}
58+
59+
for i, group := range groupListResponse.Data {
60+
if *group.ID == groupID {
61+
return &groupListResponse.Data[i], nil
62+
}
63+
}
64+
65+
return nil, fmt.Errorf("Group with ID %d not found", groupID)
66+
}
67+
68+
func (c *Client) CreateGroup(name string, assignByDefault bool, ssoMappingGroups []string) (*Group, error) {
69+
newGroup := Group{
70+
AccountID: c.AccountID,
71+
Name: name,
72+
AssignByDefault: assignByDefault,
73+
SSOMappingGroups: ssoMappingGroups,
74+
State: STATE_ACTIVE, // TODO: make variable
75+
}
76+
newGroupData, err := json.Marshal(newGroup)
77+
if err != nil {
78+
return nil, err
79+
}
80+
81+
req, err := http.NewRequest("POST", fmt.Sprintf("%s/v3/accounts/%d/groups/", c.HostURL, c.AccountID), strings.NewReader(string(newGroupData)))
82+
if err != nil {
83+
return nil, err
84+
}
85+
86+
body, err := c.doRequest(req)
87+
if err != nil {
88+
return nil, err
89+
}
90+
91+
groupResponse := GroupResponse{}
92+
err = json.Unmarshal(body, &groupResponse)
93+
if err != nil {
94+
return nil, err
95+
}
96+
97+
return &groupResponse.Data, nil
98+
}
99+
100+
func (c *Client) UpdateGroup(groupID int, group Group) (*Group, error) {
101+
groupData, err := json.Marshal(group)
102+
if err != nil {
103+
return nil, err
104+
}
105+
106+
req, err := http.NewRequest("POST", fmt.Sprintf("%s/v3/accounts/%s/groups/%d/", c.HostURL, strconv.Itoa(c.AccountID), groupID), strings.NewReader(string(groupData)))
107+
if err != nil {
108+
return nil, err
109+
}
110+
111+
body, err := c.doRequest(req)
112+
if err != nil {
113+
return nil, err
114+
}
115+
116+
groupResponse := GroupResponse{}
117+
err = json.Unmarshal(body, &groupResponse)
118+
if err != nil {
119+
return nil, err
120+
}
121+
122+
return &groupResponse.Data, nil
123+
}

pkg/dbt_cloud/user.go

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package dbt_cloud
2+
3+
import (
4+
"encoding/json"
5+
"fmt"
6+
"net/http"
7+
"strconv"
8+
)
9+
10+
type User struct {
11+
ID int `json:"id"`
12+
Email string `json:"email"`
13+
}
14+
15+
type UserListResponse struct {
16+
Data []User `json:"data"`
17+
Status ResponseStatus `json:"status"`
18+
}
19+
20+
func (c *Client) GetUser(email string) (*User, error) {
21+
req, err := http.NewRequest("GET", fmt.Sprintf("%s/v2/accounts/%s/users/", c.HostURL, strconv.Itoa(c.AccountID)), nil)
22+
if err != nil {
23+
return nil, err
24+
}
25+
26+
body, err := c.doRequest(req)
27+
if err != nil {
28+
return nil, err
29+
}
30+
31+
userListResponse := UserListResponse{}
32+
err = json.Unmarshal(body, &userListResponse)
33+
if err != nil {
34+
return nil, err
35+
}
36+
37+
for i, user := range userListResponse.Data {
38+
if user.Email == email {
39+
return &userListResponse.Data[i], nil
40+
}
41+
}
42+
43+
return nil, fmt.Errorf("Did not find user with email %s", email)
44+
}

pkg/provider/provider.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ func Provider() *schema.Provider {
3434
},
3535
},
3636
DataSourcesMap: map[string]*schema.Resource{
37+
"dbt_cloud_group": data_sources.DatasourceGroup(),
3738
"dbt_cloud_job": data_sources.DatasourceJob(),
3839
"dbt_cloud_project": data_sources.DatasourceProject(),
3940
"dbt_cloud_environment": data_sources.DatasourceEnvironment(),
@@ -50,6 +51,7 @@ func Provider() *schema.Provider {
5051
"dbt_cloud_snowflake_credential": resources.ResourceSnowflakeCredential(),
5152
"dbt_cloud_connection": resources.ResourceConnection(),
5253
"dbt_cloud_repository": resources.ResourceRepository(),
54+
"dbt_cloud_group": resources.ResourceGroup(),
5355
},
5456
ConfigureContextFunc: providerConfigure,
5557
}

0 commit comments

Comments
 (0)