Skip to content

Commit 65c1c50

Browse files
authored
Merge pull request #131 from DrFaust92/group-permission
add group permission resource
2 parents 1b4aac2 + 9810afc commit 65c1c50

File tree

6 files changed

+377
-39
lines changed

6 files changed

+377
-39
lines changed

bitbucket/provider.go

Lines changed: 24 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -68,37 +68,38 @@ func Provider() *schema.Provider {
6868
},
6969
ConfigureFunc: providerConfigure,
7070
ResourcesMap: map[string]*schema.Resource{
71-
"bitbucket_hook": resourceHook(),
72-
"bitbucket_group": resourceGroup(),
73-
"bitbucket_group_membership": resourceGroupMembership(),
74-
"bitbucket_default_reviewers": resourceDefaultReviewers(),
75-
"bitbucket_repository": resourceRepository(),
76-
"bitbucket_forked_repository": resourceForkedRepository(),
77-
"bitbucket_repository_variable": resourceRepositoryVariable(),
78-
"bitbucket_project": resourceProject(),
79-
"bitbucket_project_branching_model": resourceProjectBranchingModel(),
80-
"bitbucket_project_default_reviewers": resourceProjectDefaultReviewers(),
81-
"bitbucket_deploy_key": resourceDeployKey(),
82-
"bitbucket_pipeline_ssh_key": resourcePipelineSshKey(),
83-
"bitbucket_pipeline_ssh_known_host": resourcePipelineSshKnownHost(),
84-
"bitbucket_pipeline_schedule": resourcePipelineSchedule(),
85-
"bitbucket_ssh_key": resourceSshKey(),
86-
"bitbucket_branch_restriction": resourceBranchRestriction(),
87-
"bitbucket_branching_model": resourceBranchingModel(),
88-
"bitbucket_deployment": resourceDeployment(),
89-
"bitbucket_deployment_variable": resourceDeploymentVariable(),
90-
"bitbucket_workspace_hook": resourceWorkspaceHook(),
71+
"bitbucket_branch_restriction": resourceBranchRestriction(),
72+
"bitbucket_branching_model": resourceBranchingModel(),
73+
"bitbucket_default_reviewers": resourceDefaultReviewers(),
74+
"bitbucket_deploy_key": resourceDeployKey(),
75+
"bitbucket_deployment": resourceDeployment(),
76+
"bitbucket_deployment_variable": resourceDeploymentVariable(),
77+
"bitbucket_forked_repository": resourceForkedRepository(),
78+
"bitbucket_group": resourceGroup(),
79+
"bitbucket_group_membership": resourceGroupMembership(),
80+
"bitbucket_hook": resourceHook(),
81+
"bitbucket_pipeline_schedule": resourcePipelineSchedule(),
82+
"bitbucket_pipeline_ssh_key": resourcePipelineSshKey(),
83+
"bitbucket_pipeline_ssh_known_host": resourcePipelineSshKnownHost(),
84+
"bitbucket_project": resourceProject(),
85+
"bitbucket_project_branching_model": resourceProjectBranchingModel(),
86+
"bitbucket_project_default_reviewers": resourceProjectDefaultReviewers(),
87+
"bitbucket_repository": resourceRepository(),
88+
"bitbucket_repository_group_permission": resourceRepositoryGroupPermission(),
89+
"bitbucket_repository_variable": resourceRepositoryVariable(),
90+
"bitbucket_ssh_key": resourceSshKey(),
91+
"bitbucket_workspace_hook": resourceWorkspaceHook(),
9192
},
9293
DataSourcesMap: map[string]*schema.Resource{
94+
"bitbucket_current_user": dataCurrentUser(),
9395
"bitbucket_group": dataGroup(),
94-
"bitbucket_groups": dataGroups(),
9596
"bitbucket_group_members": dataGroupMembers(),
97+
"bitbucket_groups": dataGroups(),
98+
"bitbucket_hook_types": dataHookTypes(),
9699
"bitbucket_ip_ranges": dataIPRanges(),
97100
"bitbucket_pipeline_oidc_config": dataPipelineOidcConfig(),
98101
"bitbucket_pipeline_oidc_config_keys": dataPipelineOidcConfigKeys(),
99-
"bitbucket_hook_types": dataHookTypes(),
100102
"bitbucket_user": dataUser(),
101-
"bitbucket_current_user": dataCurrentUser(),
102103
"bitbucket_workspace": dataWorkspace(),
103104
"bitbucket_workspace_members": dataWorkspaceMembers(),
104105
},
Lines changed: 187 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,187 @@
1+
package bitbucket
2+
3+
import (
4+
"bytes"
5+
"context"
6+
"encoding/json"
7+
"fmt"
8+
"io"
9+
"log"
10+
"net/http"
11+
"strings"
12+
13+
"github.com/DrFaust92/bitbucket-go-client"
14+
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
15+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
16+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
17+
)
18+
19+
type RepositoryGroupPermission struct {
20+
Permission string `json:"permission"`
21+
Group *RepositoryGroup `json:"group,omitempty"`
22+
}
23+
24+
type RepositoryGroup struct {
25+
Name string `json:"name,omitempty"`
26+
Slug string `json:"slug,omitempty"`
27+
Workspace bitbucket.Workspace `json:"workspace,omitempty"`
28+
}
29+
30+
func resourceRepositoryGroupPermission() *schema.Resource {
31+
return &schema.Resource{
32+
CreateWithoutTimeout: resourceRepositoryGroupPermissionPut,
33+
ReadWithoutTimeout: resourceRepositoryGroupPermissionRead,
34+
UpdateWithoutTimeout: resourceRepositoryGroupPermissionPut,
35+
DeleteWithoutTimeout: resourceRepositoryGroupPermissionDelete,
36+
Importer: &schema.ResourceImporter{
37+
StateContext: schema.ImportStatePassthroughContext,
38+
},
39+
40+
Schema: map[string]*schema.Schema{
41+
"workspace": {
42+
Type: schema.TypeString,
43+
Required: true,
44+
ForceNew: true,
45+
},
46+
"repo_slug": {
47+
Type: schema.TypeString,
48+
Required: true,
49+
ForceNew: true,
50+
},
51+
"group_slug": {
52+
Type: schema.TypeString,
53+
Required: true,
54+
ForceNew: true,
55+
},
56+
"permission": {
57+
Type: schema.TypeString,
58+
Required: true,
59+
ValidateFunc: validation.StringInSlice([]string{"admin", "write", "read"}, false),
60+
},
61+
},
62+
}
63+
}
64+
65+
func createRepositoryGroupPermission(d *schema.ResourceData) *RepositoryGroupPermission {
66+
67+
permission := &RepositoryGroupPermission{
68+
Permission: d.Get("permission").(string),
69+
}
70+
71+
return permission
72+
}
73+
74+
func resourceRepositoryGroupPermissionPut(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
75+
client := m.(Clients).httpClient
76+
permission := createRepositoryGroupPermission(d)
77+
78+
payload, err := json.Marshal(permission)
79+
if err != nil {
80+
return diag.FromErr(err)
81+
}
82+
83+
workspace := d.Get("workspace").(string)
84+
repoSlug := d.Get("repo_slug").(string)
85+
groupSlug := d.Get("group_slug").(string)
86+
87+
permissionReq, err := client.Put(fmt.Sprintf("2.0/repositories/%s/%s/permissions-config/groups/%s",
88+
workspace,
89+
repoSlug,
90+
groupSlug,
91+
), bytes.NewBuffer(payload))
92+
93+
if err != nil {
94+
return diag.FromErr(err)
95+
}
96+
97+
body, readerr := io.ReadAll(permissionReq.Body)
98+
if readerr != nil {
99+
return diag.FromErr(readerr)
100+
}
101+
102+
decodeerr := json.Unmarshal(body, &permission)
103+
if decodeerr != nil {
104+
return diag.FromErr(decodeerr)
105+
}
106+
107+
if d.IsNewResource() {
108+
d.SetId(fmt.Sprintf("%s:%s:%s", workspace, repoSlug, groupSlug))
109+
}
110+
111+
return resourceRepositoryGroupPermissionRead(ctx, d, m)
112+
}
113+
114+
func resourceRepositoryGroupPermissionRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
115+
client := m.(Clients).httpClient
116+
117+
workspace, repoSlug, groupSlug, err := repositoryGroupPermissionId(d.Id())
118+
if err != nil {
119+
return diag.FromErr(err)
120+
}
121+
122+
permissionReq, err := client.Get(fmt.Sprintf("2.0/repositories/%s/%s/permissions-config/groups/%s",
123+
workspace,
124+
repoSlug,
125+
groupSlug,
126+
))
127+
128+
if permissionReq.StatusCode == http.StatusNotFound {
129+
log.Printf("[WARN] Repository Group Permission (%s) not found, removing from state", d.Id())
130+
d.SetId("")
131+
return nil
132+
}
133+
134+
if err != nil {
135+
return diag.FromErr(err)
136+
}
137+
138+
var permission RepositoryGroupPermission
139+
140+
body, readerr := io.ReadAll(permissionReq.Body)
141+
if readerr != nil {
142+
return diag.FromErr(readerr)
143+
}
144+
145+
log.Printf("Repository Group Permission raw is: %#v", string(body))
146+
147+
decodeerr := json.Unmarshal(body, &permission)
148+
if decodeerr != nil {
149+
return diag.FromErr(decodeerr)
150+
}
151+
152+
log.Printf("Repository Group Permission decoded is: %#v", permission)
153+
154+
d.Set("permission", permission.Permission)
155+
d.Set("group_slug", permission.Group.Slug)
156+
d.Set("workspace", permission.Group.Workspace.Slug)
157+
d.Set("repo_slug", repoSlug)
158+
159+
return nil
160+
}
161+
162+
func resourceRepositoryGroupPermissionDelete(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
163+
client := m.(Clients).httpClient
164+
165+
workspace, repoSlug, groupSlug, err := repositoryGroupPermissionId(d.Id())
166+
if err != nil {
167+
return diag.FromErr(err)
168+
}
169+
170+
_, err = client.Delete(fmt.Sprintf("2.0/repositories/%s/%s/permissions-config/groups/%s",
171+
workspace,
172+
repoSlug,
173+
groupSlug,
174+
))
175+
176+
return diag.FromErr(err)
177+
}
178+
179+
func repositoryGroupPermissionId(id string) (string, string, string, error) {
180+
parts := strings.Split(id, ":")
181+
182+
if len(parts) != 3 {
183+
return "", "", "", fmt.Errorf("unexpected format of ID (%q), expected WORKSPACE:REPO-SLUG:GROUP-SLUG", id)
184+
}
185+
186+
return parts[0], parts[1], parts[2], nil
187+
}
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
package bitbucket
2+
3+
import (
4+
"fmt"
5+
"net/http"
6+
"os"
7+
"testing"
8+
9+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest"
10+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
11+
"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
12+
)
13+
14+
func TestAccBitbucketRepositoryGroupPermission_basic(t *testing.T) {
15+
var repositoryGroupPermission RepositoryGroupPermission
16+
resourceName := "bitbucket_repository_group_permission.test"
17+
workspace := os.Getenv("BITBUCKET_TEAM")
18+
rName := acctest.RandomWithPrefix("tf-test")
19+
20+
resource.Test(t, resource.TestCase{
21+
PreCheck: func() { testAccPreCheck(t) },
22+
Providers: testAccProviders,
23+
CheckDestroy: testAccCheckBitbucketRepositoryGroupPermissionDestroy,
24+
Steps: []resource.TestStep{
25+
{
26+
Config: testAccBitbucketRepositoryGroupPermissionConfig(workspace, rName, "read"),
27+
Check: resource.ComposeTestCheckFunc(
28+
testAccCheckBitbucketRepositoryGroupPermissionExists(resourceName, &repositoryGroupPermission),
29+
resource.TestCheckResourceAttrPair(resourceName, "repo_slug", "bitbucket_repository.test", "name"),
30+
resource.TestCheckResourceAttrPair(resourceName, "group_slug", "bitbucket_group.test", "slug"),
31+
resource.TestCheckResourceAttr(resourceName, "workspace", workspace),
32+
resource.TestCheckResourceAttr(resourceName, "permission", "read"),
33+
),
34+
},
35+
{
36+
ResourceName: resourceName,
37+
ImportState: true,
38+
ImportStateVerify: true,
39+
},
40+
{
41+
Config: testAccBitbucketRepositoryGroupPermissionConfig(workspace, rName, "write"),
42+
Check: resource.ComposeTestCheckFunc(
43+
testAccCheckBitbucketRepositoryGroupPermissionExists(resourceName, &repositoryGroupPermission),
44+
resource.TestCheckResourceAttrPair(resourceName, "repo_slug", "bitbucket_repository.test", "name"),
45+
resource.TestCheckResourceAttrPair(resourceName, "group_slug", "bitbucket_group.test", "slug"),
46+
resource.TestCheckResourceAttr(resourceName, "workspace", workspace),
47+
resource.TestCheckResourceAttr(resourceName, "permission", "write"),
48+
),
49+
},
50+
},
51+
})
52+
}
53+
54+
func testAccCheckBitbucketRepositoryGroupPermissionDestroy(s *terraform.State) error {
55+
client := testAccProvider.Meta().(Clients).httpClient
56+
for _, rs := range s.RootModule().Resources {
57+
if rs.Type != "bitbucket_repository_group_permission" {
58+
continue
59+
}
60+
61+
response, err := client.Get(fmt.Sprintf("2.0/repositories/%s/%s/permissions-config/groups/%s", rs.Primary.Attributes["workspace"], rs.Primary.Attributes["repo_slug"], rs.Primary.Attributes["group_slug"]))
62+
63+
if err == nil {
64+
return fmt.Errorf("The resource was found should have errored")
65+
}
66+
67+
if response.StatusCode != http.StatusNotFound {
68+
return fmt.Errorf("Repository Group Permission still exists")
69+
}
70+
71+
}
72+
return nil
73+
}
74+
75+
func testAccCheckBitbucketRepositoryGroupPermissionExists(n string, repositoryGroupPermission *RepositoryGroupPermission) resource.TestCheckFunc {
76+
return func(s *terraform.State) error {
77+
rs, ok := s.RootModule().Resources[n]
78+
if !ok {
79+
return fmt.Errorf("Not found %s", n)
80+
}
81+
if rs.Primary.ID == "" {
82+
return fmt.Errorf("No Repository Group Permission ID is set")
83+
}
84+
return nil
85+
}
86+
}
87+
88+
func testAccBitbucketRepositoryGroupPermissionConfig(workspace, rName, permission string) string {
89+
return fmt.Sprintf(`
90+
resource "bitbucket_repository" "test" {
91+
owner = %[1]q
92+
name = %[2]q
93+
}
94+
95+
resource "bitbucket_group" "test" {
96+
workspace = %[1]q
97+
name = %[2]q
98+
}
99+
100+
resource "bitbucket_repository_group_permission" "test" {
101+
workspace = %[1]q
102+
repo_slug = bitbucket_repository.test.name
103+
group_slug = bitbucket_group.test.slug
104+
permission = %[3]q
105+
}
106+
`, workspace, rName, permission)
107+
}

0 commit comments

Comments
 (0)