Skip to content

Commit

Permalink
GH-116 Update Groups implementation (#128)
Browse files Browse the repository at this point in the history
* GH-116 Update Groups implementation

This is to match the latest Bitbucket behaviour, specifically the `auto_add` has been replaced by an additional permission entry `none`. Appears as though groups are auto-added to all repositories with a default permission, that can then be overridden on a per-repository basis.

* GH-116 Address issue with updating Branch Restrictions

Bitbucket's API returns HTTP 400 when trying to update an existing branch restriction, so instead we'll delete and re-create.
  • Loading branch information
zahiar authored Sep 25, 2022
1 parent c3aab65 commit 3d59929
Show file tree
Hide file tree
Showing 14 changed files with 32 additions and 58 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
.idea
*.tfstate
*.tfstate.backup
examples
23 changes: 16 additions & 7 deletions bitbucket/api/v1/groups.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,13 @@ type Group struct {
Uuid string `json:"uuid"`
}
Name string `json:"name"`
AutoAdd bool `json:"auto_add"`
Slug string `json:"slug"`
Permission string `json:"permission"`
}

type GroupOptions struct {
OwnerUuid string
Name string
AutoAdd bool
Slug string
Permission string
}
Expand Down Expand Up @@ -61,6 +59,10 @@ func (g *Groups) Get(gro *GroupOptions) (*Group, error) {
return nil, fmt.Errorf("no group found")
}

if result[0].Permission == "" {
result[0].Permission = "none"
}

return &result[0], nil
}

Expand Down Expand Up @@ -92,20 +94,27 @@ func (g *Groups) Create(gro *GroupOptions) (*Group, error) {
return nil, err
}

if result.Permission == "" {
result.Permission = "none"
}

return result, nil
}

func (g *Groups) Update(gro *GroupOptions) (*Group, error) {
url := fmt.Sprintf("%s/groups/%s/%s", g.client.ApiBaseUrl, gro.OwnerUuid, gro.Slug)

groupPermission := &gro.Permission
if *groupPermission == "none" {
groupPermission = nil
}

requestBody := struct {
Name string `json:"name,omitempty"`
AutoAdd bool `json:"auto_add,omitempty"`
Permission string `json:"permission,omitempty"`
Name string `json:"name,omitempty"`
Permission *string `json:"permission"`
}{
Name: gro.Name,
AutoAdd: gro.AutoAdd,
Permission: gro.Permission,
Permission: groupPermission,
}
requestBodyJson, err := json.Marshal(requestBody)
if err != nil {
Expand Down
11 changes: 3 additions & 8 deletions bitbucket/api/v1/groups_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,7 @@ func TestGroups(t *testing.T) {

assert.NoError(t, err)
assert.Equal(t, name, group.Name)
assert.False(t, group.AutoAdd)
assert.Empty(t, group.Permission)
assert.Equal(t, "none", group.Permission)

groupResourceSlug = group.Slug
})
Expand All @@ -46,23 +45,20 @@ func TestGroups(t *testing.T) {

assert.NoError(t, err)
assert.Equal(t, name, group.Name)
assert.False(t, group.AutoAdd)
assert.Empty(t, group.Permission)
assert.Equal(t, "none", group.Permission)
assert.Equal(t, groupResourceSlug, group.Slug)
})

t.Run("update", func(t *testing.T) {
opt := &GroupOptions{
OwnerUuid: c.Auth.Username,
Slug: groupResourceSlug,
AutoAdd: true,
Permission: "write",
}
group, err := c.Groups.Update(opt)

assert.NoError(t, err)
assert.Equal(t, name, group.Name)
assert.True(t, group.AutoAdd)
assert.Equal(t, "write", group.Permission)
assert.Equal(t, groupResourceSlug, group.Slug)
})
Expand Down Expand Up @@ -101,8 +97,7 @@ func TestGroupsGracefullyHandleNoReturnedGroupsForInvalidSlug(t *testing.T) {
assert.NoError(t, err)

assert.Equal(t, name, group.Name)
assert.False(t, group.AutoAdd)
assert.Empty(t, group.Permission)
assert.Equal(t, "none", group.Permission)

groupResourceSlug = group.Slug
})
Expand Down
5 changes: 0 additions & 5 deletions bitbucket/data_source_bitbucket_group.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,6 @@ func dataSourceBitbucketGroup() *schema.Resource {
Type: schema.TypeString,
Required: true,
},
"auto_add": {
Description: "Whether this group is auto-added to all future repositories.",
Type: schema.TypeBool,
Computed: true,
},
"permission": {
Description: "The permission this group will have over repositories. Must be one of 'read', 'write', 'admin'.",
Type: schema.TypeString,
Expand Down
1 change: 0 additions & 1 deletion bitbucket/data_source_bitbucket_group_permission_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ func TestAccBitbucketGroupPermissionDataSource_basic(t *testing.T) {
resource "bitbucket_group" "testacc" {
workspace = data.bitbucket_workspace.testacc.uuid
name = "%s"
auto_add = true
permission = "read"
}
Expand Down
2 changes: 0 additions & 2 deletions bitbucket/data_source_bitbucket_group_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ func TestAccBitbucketGroupDataSource_basic(t *testing.T) {
resource "bitbucket_group" "testacc" {
workspace = data.bitbucket_workspace.testacc.id
name = "%s"
auto_add = true
permission = "read"
}
Expand All @@ -37,7 +36,6 @@ func TestAccBitbucketGroupDataSource_basic(t *testing.T) {
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr("data.bitbucket_group.testacc", "workspace", workspaceSlug),
resource.TestCheckResourceAttr("data.bitbucket_group.testacc", "name", groupName),
resource.TestCheckResourceAttr("data.bitbucket_group.testacc", "auto_add", "true"),
resource.TestCheckResourceAttr("data.bitbucket_group.testacc", "permission", "read"),
resource.TestCheckResourceAttr("data.bitbucket_group.testacc", "slug", groupName),
resource.TestCheckResourceAttrSet("data.bitbucket_group.testacc", "id"),
Expand Down
1 change: 1 addition & 0 deletions bitbucket/resource_bitbucket_branch_restriction.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ func resourceBitbucketBranchRestriction() *schema.Resource {
"reset_pullrequest_approvals_on_change",
"delete",
}, false),
ForceNew: true,
},
"value": {
Description: "A configurable value used by the following restrictions: `require_passing_builds_to_merge` uses it to define the number of minimum number of passing builds, `require_approvals_to_merge` uses it to define the minimum number of approvals before the PR can be merged, `require_default_reviewer_approvals_to_merge` uses it to define the minimum number of approvals from default reviewers before the PR can be merged.",
Expand Down
15 changes: 4 additions & 11 deletions bitbucket/resource_bitbucket_group.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,17 +42,12 @@ func resourceBitbucketGroup() *schema.Resource {
Type: schema.TypeString,
Computed: true,
},
"auto_add": {
Description: "Whether this group is auto-added to all future repositories.",
Type: schema.TypeBool,
Optional: true,
Default: false,
},
"permission": {
Description: "The permission this group will have over repositories. Must be one of 'read', 'write', 'admin'.",
Description: "The global permission this group will have over all repositories. Must be one of 'none', 'read', 'write', 'admin'.",
Type: schema.TypeString,
Optional: true,
ValidateFunc: validation.StringInSlice([]string{"read", "write", "admin"}, false),
Default: "none",
ValidateFunc: validation.StringInSlice([]string{"none", "read", "write", "admin"}, false),
},
},
}
Expand All @@ -73,7 +68,7 @@ func resourceBitbucketGroupCreate(ctx context.Context, resourceData *schema.Reso

_ = resourceData.Set("slug", group.Slug)

// We do an update as well, as that's where the other options like auto-add/permissions are set.
// We do an update as well, as that's where the other options like permissions are set.
// The POST endpoint only accepts a name, and just creates a group without setting any other options.
return resourceBitbucketGroupUpdate(ctx, resourceData, meta)
}
Expand All @@ -92,7 +87,6 @@ func resourceBitbucketGroupRead(ctx context.Context, resourceData *schema.Resour
}

_ = resourceData.Set("name", group.Name)
_ = resourceData.Set("auto_add", group.AutoAdd)
_ = resourceData.Set("permission", group.Permission)

resourceData.SetId(generateGroupResourceId(group.Owner.Uuid, group.Slug))
Expand All @@ -108,7 +102,6 @@ func resourceBitbucketGroupUpdate(ctx context.Context, resourceData *schema.Reso
OwnerUuid: resourceData.Get("workspace").(string),
Slug: resourceData.Get("slug").(string),
Name: resourceData.Get("name").(string),
AutoAdd: resourceData.Get("auto_add").(bool),
Permission: resourceData.Get("permission").(string),
},
)
Expand Down
1 change: 0 additions & 1 deletion bitbucket/resource_bitbucket_group_member_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ func TestAccBitbucketGroupMemberResource_basic(t *testing.T) {
resource "bitbucket_group" "testacc" {
workspace = data.bitbucket_workspace.testacc.uuid
name = "%s"
auto_add = true
permission = "read"
}
Expand Down
1 change: 0 additions & 1 deletion bitbucket/resource_bitbucket_group_permission_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ func TestAccBitbucketGroupPermissionResource_basic(t *testing.T) {
resource "bitbucket_group" "testacc" {
workspace = data.bitbucket_workspace.testacc.uuid
name = "%s"
auto_add = true
permission = "read"
}
Expand Down
15 changes: 1 addition & 14 deletions bitbucket/resource_bitbucket_group_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,10 @@ func TestAccBitbucketGroupResource_basic(t *testing.T) {
resource "bitbucket_group" "testacc" {
workspace = data.bitbucket_workspace.testacc.uuid
name = "%s"
auto_add = true
permission = "read"
}`, workspaceSlug, groupName),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr("bitbucket_group.testacc", "name", groupName),
resource.TestCheckResourceAttr("bitbucket_group.testacc", "auto_add", "true"),
resource.TestCheckResourceAttr("bitbucket_group.testacc", "permission", "read"),
resource.TestCheckResourceAttr("bitbucket_group.testacc", "slug", groupName),

Expand Down Expand Up @@ -73,12 +71,10 @@ func TestAccBitbucketGroupResource_changeName(t *testing.T) {
resource "bitbucket_group" "testacc" {
workspace = data.bitbucket_workspace.testacc.uuid
name = "%s"
auto_add = true
permission = "read"
}`, workspaceSlug, groupName),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr("bitbucket_group.testacc", "name", groupName),
resource.TestCheckResourceAttr("bitbucket_group.testacc", "auto_add", "true"),
resource.TestCheckResourceAttr("bitbucket_group.testacc", "permission", "read"),
resource.TestCheckResourceAttr("bitbucket_group.testacc", "slug", groupName),

Expand All @@ -95,12 +91,10 @@ func TestAccBitbucketGroupResource_changeName(t *testing.T) {
resource "bitbucket_group" "testacc" {
workspace = data.bitbucket_workspace.testacc.uuid
name = "%s"
auto_add = true
permission = "read"
}`, workspaceSlug, newGroupName),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr("bitbucket_group.testacc", "name", newGroupName),
resource.TestCheckResourceAttr("bitbucket_group.testacc", "auto_add", "true"),
resource.TestCheckResourceAttr("bitbucket_group.testacc", "permission", "read"),
resource.TestCheckResourceAttr("bitbucket_group.testacc", "slug", newGroupName),

Expand Down Expand Up @@ -139,12 +133,10 @@ func TestAccBitbucketGroupResource_changeProperties(t *testing.T) {
resource "bitbucket_group" "testacc" {
workspace = data.bitbucket_workspace.testacc.uuid
name = "%s"
auto_add = true
permission = "read"
}`, workspaceSlug, groupName),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr("bitbucket_group.testacc", "name", groupName),
resource.TestCheckResourceAttr("bitbucket_group.testacc", "auto_add", "true"),
resource.TestCheckResourceAttr("bitbucket_group.testacc", "permission", "read"),
resource.TestCheckResourceAttr("bitbucket_group.testacc", "slug", groupName),

Expand All @@ -161,12 +153,10 @@ func TestAccBitbucketGroupResource_changeProperties(t *testing.T) {
resource "bitbucket_group" "testacc" {
workspace = data.bitbucket_workspace.testacc.uuid
name = "%s"
auto_add = false
permission = "write"
}`, workspaceSlug, groupName),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr("bitbucket_group.testacc", "name", groupName),
resource.TestCheckResourceAttr("bitbucket_group.testacc", "auto_add", "false"),
resource.TestCheckResourceAttr("bitbucket_group.testacc", "permission", "write"),
resource.TestCheckResourceAttr("bitbucket_group.testacc", "slug", groupName),

Expand Down Expand Up @@ -208,8 +198,7 @@ func TestAccBitbucketGroupResource_withoutProperties(t *testing.T) {
}`, workspaceSlug, groupName),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr("bitbucket_group.testacc", "name", groupName),
resource.TestCheckResourceAttr("bitbucket_group.testacc", "auto_add", "false"),
resource.TestCheckResourceAttr("bitbucket_group.testacc", "permission", ""),
resource.TestCheckResourceAttr("bitbucket_group.testacc", "permission", "none"),
resource.TestCheckResourceAttr("bitbucket_group.testacc", "slug", groupName),

resource.TestCheckResourceAttrSet("bitbucket_group.testacc", "workspace"),
Expand All @@ -225,12 +214,10 @@ func TestAccBitbucketGroupResource_withoutProperties(t *testing.T) {
resource "bitbucket_group" "testacc" {
workspace = data.bitbucket_workspace.testacc.uuid
name = "%s"
auto_add = true
permission = "write"
}`, workspaceSlug, groupName),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr("bitbucket_group.testacc", "name", groupName),
resource.TestCheckResourceAttr("bitbucket_group.testacc", "auto_add", "true"),
resource.TestCheckResourceAttr("bitbucket_group.testacc", "permission", "write"),
resource.TestCheckResourceAttr("bitbucket_group.testacc", "slug", groupName),

Expand Down
7 changes: 4 additions & 3 deletions bitbucket/resource_bitbucket_repository_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ func TestAccBitbucketRepositoryResource_basic(t *testing.T) {
resource.TestCheckResourceAttr("bitbucket_repository.testacc", "project_key", projectKey),
resource.TestCheckResourceAttr("bitbucket_repository.testacc", "description", ""),
resource.TestCheckResourceAttr("bitbucket_repository.testacc", "is_private", "true"),
resource.TestCheckResourceAttr("bitbucket_repository.testacc", "has_wiki", "true"),
resource.TestCheckResourceAttr("bitbucket_repository.testacc", "has_wiki", "false"),
resource.TestCheckResourceAttr("bitbucket_repository.testacc", "fork_policy", "no_forks"),
resource.TestCheckResourceAttr("bitbucket_repository.testacc", "enable_pipelines", "false"),
resource.TestCheckResourceAttrSet("bitbucket_repository.testacc", "id"),
Expand Down Expand Up @@ -78,7 +78,7 @@ func TestAccBitbucketRepositoryResource_basic(t *testing.T) {
resource.TestCheckResourceAttr("bitbucket_repository.testacc", "project_key", projectKey),
resource.TestCheckResourceAttr("bitbucket_repository.testacc", "description", repoDescription),
resource.TestCheckResourceAttr("bitbucket_repository.testacc", "is_private", "true"),
resource.TestCheckResourceAttr("bitbucket_repository.testacc", "has_wiki", "true"),
resource.TestCheckResourceAttr("bitbucket_repository.testacc", "has_wiki", "false"),
resource.TestCheckResourceAttr("bitbucket_repository.testacc", "fork_policy", repoForkPolicy),
resource.TestCheckResourceAttr("bitbucket_repository.testacc", "enable_pipelines", "false"),
resource.TestCheckResourceAttrSet("bitbucket_repository.testacc", "id"),
Expand All @@ -103,6 +103,7 @@ func TestAccBitbucketRepositoryResource_basic(t *testing.T) {
description = "%s"
fork_policy = "%s"
enable_pipelines = true
has_wiki = true
}`, workspaceSlug, projectName, projectKey, repoName, repoDescription, repoForkPolicy),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr("bitbucket_repository.testacc", "workspace", workspaceSlug),
Expand Down Expand Up @@ -133,7 +134,7 @@ func TestValidateRepositoryName(t *testing.T) {
validator := validateRepositoryName(invalidName, nil)
assert.True(t, validator.HasError())

validNames := []string{"abc-def","foo.bar"}
validNames := []string{"abc-def", "foo.bar"}

for _, validName := range validNames {
validator = validateRepositoryName(validName, nil)
Expand Down
3 changes: 1 addition & 2 deletions docs/data-sources/bitbucket_group.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,4 @@ The following arguments are supported:
In addition to the arguments above, the following additional attributes are exported:
* `id` - The ID of the group.
* `name` - A human-readable name of the group.
* `auto_add` - A boolean to state whether this group is auto-added to all future repositories.
* `permission` - The permission this group will have over repositories. Is one of 'read', 'write', or 'admin'.
* `permission` - The global permission this group will have over all repositories. Is one of 'none', 'read', 'write', 'admin'.
4 changes: 1 addition & 3 deletions docs/resources/bitbucket_group.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ Manage a group within Bitbucket.
resource "bitbucket_group" "example" {
workspace = "{workspace-uuid}"
name = "Example Group"
auto_add = false
permission = "read"
}
```
Expand All @@ -15,8 +14,7 @@ resource "bitbucket_group" "example" {
The following arguments are supported:
* `workspace` - (Required) The UUID (including the enclosing `{}`) of the workspace the group belongs to.
* `name` - (Required) A human-readable name of the group.
* `auto_add` - (Optional) A boolean to state whether this group is auto-added to all future repositories.
* `permission` - (Optional) The permission this group will have over repositories. Is one of 'read', 'write', or 'admin'.
* `permission` - (Optional) The global permission this group will have over all repositories. Must be one of 'none', 'read', 'write', 'admin'.

## Attribute Reference
In addition to the arguments above, the following additional attributes are exported:
Expand Down

0 comments on commit 3d59929

Please sign in to comment.