Skip to content

Commit

Permalink
Merge pull request #196 from DrFaust92/project_perm
Browse files Browse the repository at this point in the history
project user and group permission resources
  • Loading branch information
DrFaust92 authored Feb 10, 2024
2 parents 8f8b5ba + c7dd69e commit f5a9824
Show file tree
Hide file tree
Showing 7 changed files with 674 additions and 0 deletions.
2 changes: 2 additions & 0 deletions bitbucket/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@ func Provider() *schema.Provider {
"bitbucket_project": resourceProject(),
"bitbucket_project_branching_model": resourceProjectBranchingModel(),
"bitbucket_project_default_reviewers": resourceProjectDefaultReviewers(),
"bitbucket_project_group_permission": resourceProjectGroupPermission(),
"bitbucket_project_user_permission": resourceProjectUserPermission(),
"bitbucket_repository": resourceRepository(),
"bitbucket_repository_group_permission": resourceRepositoryGroupPermission(),
"bitbucket_repository_user_permission": resourceRepositoryUserPermission(),
Expand Down
187 changes: 187 additions & 0 deletions bitbucket/resource_project_group_permission.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
package bitbucket

import (
"bytes"
"context"
"encoding/json"
"fmt"
"io"
"log"
"net/http"
"strings"

"github.com/DrFaust92/bitbucket-go-client"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
)

type ProjectGroupPermission struct {
Permission string `json:"permission"`
Group *ProjectGroup `json:"group,omitempty"`
}

type ProjectGroup struct {
Name string `json:"name,omitempty"`
Slug string `json:"slug,omitempty"`
Workspace bitbucket.Workspace `json:"workspace,omitempty"`
}

func resourceProjectGroupPermission() *schema.Resource {
return &schema.Resource{
CreateWithoutTimeout: resourceProjectGroupPermissionPut,
ReadWithoutTimeout: resourceProjectGroupPermissionRead,
UpdateWithoutTimeout: resourceProjectGroupPermissionPut,
DeleteWithoutTimeout: resourceProjectGroupPermissionDelete,
Importer: &schema.ResourceImporter{
StateContext: schema.ImportStatePassthroughContext,
},

Schema: map[string]*schema.Schema{
"workspace": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"project_key": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"group_slug": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"permission": {
Type: schema.TypeString,
Required: true,
ValidateFunc: validation.StringInSlice([]string{"admin", "write", "read", "create-repo"}, false),
},
},
}
}

func createProjectGroupPermission(d *schema.ResourceData) *ProjectGroupPermission {

permission := &ProjectGroupPermission{
Permission: d.Get("permission").(string),
}

return permission
}

func resourceProjectGroupPermissionPut(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
client := m.(Clients).httpClient
permission := createProjectGroupPermission(d)

payload, err := json.Marshal(permission)
if err != nil {
return diag.FromErr(err)
}

workspace := d.Get("workspace").(string)
projectKey := d.Get("project_key").(string)
groupSlug := d.Get("group_slug").(string)

permissionReq, err := client.Put(fmt.Sprintf("2.0/workspaces/%s/projects/%s/permissions-config/groups/%s",
workspace,
projectKey,
groupSlug,
), bytes.NewBuffer(payload))

if err != nil {
return diag.FromErr(err)
}

body, readerr := io.ReadAll(permissionReq.Body)
if readerr != nil {
return diag.FromErr(readerr)
}

decodeerr := json.Unmarshal(body, &permission)
if decodeerr != nil {
return diag.FromErr(decodeerr)
}

if d.IsNewResource() {
d.SetId(fmt.Sprintf("%s:%s:%s", workspace, projectKey, groupSlug))
}

return resourceProjectGroupPermissionRead(ctx, d, m)
}

func resourceProjectGroupPermissionRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
client := m.(Clients).httpClient

workspace, projectKey, groupSlug, err := projectGroupPermissionId(d.Id())
if err != nil {
return diag.FromErr(err)
}

permissionReq, err := client.Get(fmt.Sprintf("2.0/workspaces/%s/projects/%s/permissions-config/groups/%s",
workspace,
projectKey,
groupSlug,
))

if permissionReq.StatusCode == http.StatusNotFound {
log.Printf("[WARN] Project Group Permission (%s) not found, removing from state", d.Id())
d.SetId("")
return nil
}

if err != nil {
return diag.FromErr(err)
}

var permission ProjectGroupPermission

body, readerr := io.ReadAll(permissionReq.Body)
if readerr != nil {
return diag.FromErr(readerr)
}

log.Printf("Project Group Permission raw is: %#v", string(body))

decodeerr := json.Unmarshal(body, &permission)
if decodeerr != nil {
return diag.FromErr(decodeerr)
}

log.Printf("Project Group Permission decoded is: %#v", permission)

d.Set("permission", permission.Permission)
d.Set("group_slug", permission.Group.Slug)
d.Set("workspace", permission.Group.Workspace.Slug)
d.Set("project_key", projectKey)

return nil
}

func resourceProjectGroupPermissionDelete(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
client := m.(Clients).httpClient

workspace, projectKey, groupSlug, err := projectGroupPermissionId(d.Id())
if err != nil {
return diag.FromErr(err)
}

_, err = client.Delete(fmt.Sprintf("2.0/workspaces/%s/projects/%s/permissions-config/groups/%s",
workspace,
projectKey,
groupSlug,
))

return diag.FromErr(err)
}

func projectGroupPermissionId(id string) (string, string, string, error) {
parts := strings.Split(id, ":")

if len(parts) != 3 {
return "", "", "", fmt.Errorf("unexpected format of ID (%q), expected WORKSPACE:PROJECT-KEY:GROUP-SLUG", id)
}

return parts[0], parts[1], parts[2], nil
}
108 changes: 108 additions & 0 deletions bitbucket/resource_project_group_permission_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
package bitbucket

import (
"fmt"
"net/http"
"os"
"testing"

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
)

func TestAccBitbucketProjectGroupPermission_basic(t *testing.T) {
var projectGroupPermission ProjectGroupPermission
resourceName := "bitbucket_project_group_permission.test"
workspace := os.Getenv("BITBUCKET_TEAM")
rName := acctest.RandomWithPrefix("tf-test")

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckBitbucketProjectGroupPermissionDestroy,
Steps: []resource.TestStep{
{
Config: testAccBitbucketProjectGroupPermissionConfig(workspace, rName, "read"),
Check: resource.ComposeTestCheckFunc(
testAccCheckBitbucketProjectGroupPermissionExists(resourceName, &projectGroupPermission),
resource.TestCheckResourceAttrPair(resourceName, "project_key", "bitbucket_project.test", "key"),
resource.TestCheckResourceAttrPair(resourceName, "group_slug", "bitbucket_group.test", "slug"),
resource.TestCheckResourceAttr(resourceName, "workspace", workspace),
resource.TestCheckResourceAttr(resourceName, "permission", "read"),
),
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
{
Config: testAccBitbucketProjectGroupPermissionConfig(workspace, rName, "write"),
Check: resource.ComposeTestCheckFunc(
testAccCheckBitbucketProjectGroupPermissionExists(resourceName, &projectGroupPermission),
resource.TestCheckResourceAttrPair(resourceName, "project_key", "bitbucket_project.test", "key"),
resource.TestCheckResourceAttrPair(resourceName, "group_slug", "bitbucket_group.test", "slug"),
resource.TestCheckResourceAttr(resourceName, "workspace", workspace),
resource.TestCheckResourceAttr(resourceName, "permission", "write"),
),
},
},
})
}

func testAccCheckBitbucketProjectGroupPermissionDestroy(s *terraform.State) error {
client := testAccProvider.Meta().(Clients).httpClient
for _, rs := range s.RootModule().Resources {
if rs.Type != "bitbucket_project_group_permission" {
continue
}

response, err := client.Get(fmt.Sprintf("2.0/repositories/%s/%s/permissions-config/groups/%s", rs.Primary.Attributes["workspace"], rs.Primary.Attributes["project_key"], rs.Primary.Attributes["group_slug"]))

if err == nil {
return fmt.Errorf("The resource was found should have errored")
}

if response.StatusCode != http.StatusNotFound {
return fmt.Errorf("Project Group Permission still exists")
}

}
return nil
}

func testAccCheckBitbucketProjectGroupPermissionExists(n string, projectGroupPermission *ProjectGroupPermission) resource.TestCheckFunc {
return func(s *terraform.State) error {
rs, ok := s.RootModule().Resources[n]
if !ok {
return fmt.Errorf("Not found %s", n)
}
if rs.Primary.ID == "" {
return fmt.Errorf("No Project Group Permission ID is set")
}
return nil
}
}

func testAccBitbucketProjectGroupPermissionConfig(workspace, rName, permission string) string {
return fmt.Sprintf(`
resource "bitbucket_project" "test" {
owner = %[1]q
name = %[2]q
key = "GRPPERM"
}
resource "bitbucket_group" "test" {
workspace = %[1]q
name = %[2]q
}
resource "bitbucket_project_group_permission" "test" {
workspace = %[1]q
project_key = bitbucket_project.test.key
group_slug = bitbucket_group.test.slug
permission = %[3]q
}
`, workspace, rName, permission)
}
Loading

0 comments on commit f5a9824

Please sign in to comment.