Skip to content

Commit

Permalink
Merge pull request #551 from sirlatrom/fix-549
Browse files Browse the repository at this point in the history
Add data sources gitlab_project_protected_branch(es)
  • Loading branch information
nagyv committed Jan 21, 2022
2 parents 39b0b6d + 9cc7dd4 commit febe745
Show file tree
Hide file tree
Showing 7 changed files with 465 additions and 6 deletions.
49 changes: 49 additions & 0 deletions docs/data-sources/project_protected_branch.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# gitlab\_project\_protected\_branch

Provides details about a specific protected branch in a given project.

## Example Usage

```hcl
data "gitlab_project_protected_branch" "example" {
project_id = 30
name = "main"
}
```

```hcl
data "gitlab_project_protected_branch" "example" {
project_id = "foo/bar/baz"
name = "main"
}
```

## Argument Reference

The following arguments are supported:

* `project_id` - (Required) The integer or path with namespace that uniquely identifies the project.

* `name` - (Required) The name of the protected branch.

## Attributes Reference

The following attributes are exported:

* `push_access_levels`, `merge_access_levels`, `unprotect_access_levels` - Each block contains a list of which access levels, users or groups are allowed to perform the respective actions (documented below).

* `code_owner_approval_required` - Reject code pushes that change files listed in the CODEOWNERS file.

## Nested Blocks

### `push_access_levels`, `merge_access_levels`, `unprotect_access_levels`

#### Attributes

* `access_level` - The access level allowed to perform the respective action (shows as 40 - "maintainer" if `user_id` or `group_id` are present).

* `access_level_description` - A description of the allowed access level(s), or the name of the user or group if `user_id` or `group_id` are present.

* `user_id` - If present, indicates that the user is allowed to perform the respective action.

* `group_id` - If present, indicates that the group is allowed to perform the respective action.
53 changes: 53 additions & 0 deletions docs/data-sources/project_protected_branches.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# gitlab\_project\_protected\_branches

Provides details about all protected branches in a given project.

## Example Usage

```hcl
data "gitlab_project_protected_branches" "example" {
project_id = 30
}
```

```hcl
data "gitlab_project_protected_branches" "example" {
project_id = "foo/bar/baz"
}
```

## Argument Reference

The following arguments are supported:

* `project_id` - (Required) The integer or path with namespace that uniquely identifies the project.

## Attributes Reference

The following attributes are exported:

* `protected_branches` - A list of protected branches, as defined below.

## Nested Blocks

### `protected_branches`

* `id` - The ID of the protected branch.

* `name` - The name of the protected branch.

* `push_access_levels`, `merge_access_levels`, `unprotect_access_levels` - Each block contains a list of which access levels, users or groups are allowed to perform the respective actions (documented below).

* `code_owner_approval_required` - Reject code pushes that change files listed in the CODEOWNERS file.

### `push_access_levels`, `merge_access_levels`, `unprotect_access_levels`

#### Attributes

* `access_level` - The access level allowed to perform the respective action (shows as 40 - "maintainer" if `user_id` or `group_id` are present).

* `access_level_description` - A description of the allowed access level(s), or the name of the user or group if `user_id` or `group_id` are present.

* `user_id` - If present, indicates that the user is allowed to perform the respective action.

* `group_id` - If present, indicates that the group is allowed to perform the respective action.
131 changes: 131 additions & 0 deletions gitlab/data_source_gitlab_project_protected_branch.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
package gitlab

import (
"fmt"
"log"

"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/helper/validation"
"github.com/xanzy/go-gitlab"
)

func dataSourceGitlabProjectProtectedBranch() *schema.Resource {
return &schema.Resource{
Read: dataSourceGitlabProjectProtectedBranchRead,
Schema: map[string]*schema.Schema{
"project_id": {
Type: schema.TypeString,
Description: "ID or URL encoded name of project",
Required: true,
ValidateFunc: validation.StringIsNotEmpty,
},
"name": {
Type: schema.TypeString,
Description: "Name of the protected branch",
Required: true,
ValidateFunc: validation.StringIsNotEmpty,
},
"id": {
Type: schema.TypeInt,
Computed: true,
},
"push_access_levels": dataSourceGitlabProjectProtectedBranchSchemaAccessLevels(),
"merge_access_levels": dataSourceGitlabProjectProtectedBranchSchemaAccessLevels(),
"unprotect_access_levels": dataSourceGitlabProjectProtectedBranchSchemaAccessLevels(),
"code_owner_approval_required": {
Type: schema.TypeBool,
Computed: true,
},
},
}
}

func dataSourceGitlabProjectProtectedBranchSchemaAccessLevels() *schema.Schema {
return &schema.Schema{
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"access_level": {
Type: schema.TypeString,
Computed: true,
},
"access_level_description": {
Type: schema.TypeString,
Computed: true,
},
"user_id": {
Type: schema.TypeInt,
Computed: true,
},
"group_id": {
Type: schema.TypeInt,
Computed: true,
},
},
},
}
}

func dataSourceGitlabProjectProtectedBranchRead(d *schema.ResourceData, meta interface{}) error {
client := meta.(*gitlab.Client)

log.Printf("[INFO] Reading Gitlab protected branch")

project := d.Get("project_id")
name := d.Get("name").(string)

// Get protected branch by project ID/path and branch name
pb, _, err := client.ProtectedBranches.GetProtectedBranch(project, name)
if err != nil {
return fmt.Errorf("error getting protected branch (Project: %v / Name %v): %v", project, name, err)
}

if err := d.Set("push_access_levels", convertBranchAccessDescriptionsToStateBranchAccessDescriptions(pb.PushAccessLevels)); err != nil {
return err
}
if err := d.Set("merge_access_levels", convertBranchAccessDescriptionsToStateBranchAccessDescriptions(pb.MergeAccessLevels)); err != nil {
return err
}
if err := d.Set("unprotect_access_levels", convertBranchAccessDescriptionsToStateBranchAccessDescriptions(pb.UnprotectAccessLevels)); err != nil {
return err
}
if err := d.Set("code_owner_approval_required", pb.CodeOwnerApprovalRequired); err != nil {
return err
}

d.SetId(fmt.Sprintf("%d", pb.ID))

return nil
}

type stateBranchAccessDescription struct {
AccessLevel string `json:"access_level" mapstructure:"access_level"`
AccessLevelDescription string `json:"access_level_description" mapstructure:"access_level_description"`
GroupID *int `json:"group_id,omitempty" mapstructure:"group_id,omitempty"`
UserID *int `json:"user_id,omitempty" mapstructure:"user_id,omitempty"`
}

func convertBranchAccessDescriptionsToStateBranchAccessDescriptions(descriptions []*gitlab.BranchAccessDescription) []stateBranchAccessDescription {
result := make([]stateBranchAccessDescription, 0)

for _, description := range descriptions {
result = append(result, convertBranchAccessDescriptionToStateBranchAccessDescription(description))
}

return result
}

func convertBranchAccessDescriptionToStateBranchAccessDescription(description *gitlab.BranchAccessDescription) stateBranchAccessDescription {
stateDescription := stateBranchAccessDescription{
AccessLevel: accessLevel[description.AccessLevel],
AccessLevelDescription: description.AccessLevelDescription,
}
if description.UserID != 0 {
stateDescription.UserID = &description.UserID
}
if description.GroupID != 0 {
stateDescription.GroupID = &description.GroupID
}
return stateDescription
}
64 changes: 64 additions & 0 deletions gitlab/data_source_gitlab_project_protected_branch_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package gitlab

import (
"fmt"
"testing"

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

func TestAccDataGitlabProjectProtectedBranchSearch(t *testing.T) {
projectName := fmt.Sprintf("tf-%s", acctest.RandString(5))

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
{
Config: testAccDataGitlabProjectProtectedBranchConfigGetProjectSearch(projectName),
Check: resource.ComposeAggregateTestCheckFunc(
resource.TestCheckResourceAttr(
"data.gitlab_project_protected_branch.test",
"name",
"master",
),
resource.TestCheckResourceAttr(
"data.gitlab_project_protected_branch.test",
"push_access_levels.0.access_level",
"maintainer",
),
),
},
},
})
}

func testAccDataGitlabProjectProtectedBranchConfigGetProjectSearch(projectName string) string {
return fmt.Sprintf(`
resource "gitlab_project" "test" {
name = "%s"
path = "%s"
default_branch = "master"
}
resource "gitlab_branch_protection" "master" {
project = gitlab_project.test.id
branch = "master"
push_access_level = "maintainer"
merge_access_level = "developer"
}
resource "gitlab_branch_protection" "test" {
project = gitlab_project.test.id
branch = "master"
push_access_level = "maintainer"
merge_access_level = "developer"
}
data "gitlab_project_protected_branch" "test" {
project_id = gitlab_project.test.id
name = gitlab_branch_protection.master.branch
}
`, projectName, projectName)
}

0 comments on commit febe745

Please sign in to comment.