Skip to content

Commit

Permalink
Merge branch 'more-resources' of gh:stakater/terraform-provider-gitlab
Browse files Browse the repository at this point in the history
  • Loading branch information
roidelapluie committed May 2, 2019
2 parents 3ddf4ae + 2978c43 commit 11c7e32
Show file tree
Hide file tree
Showing 4 changed files with 340 additions and 0 deletions.
1 change: 1 addition & 0 deletions gitlab/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ func Provider() terraform.ResourceProvider {
},

ResourcesMap: map[string]*schema.Resource{
"gitlab_branch_protection": resourceGitlabBranchProtection(),
"gitlab_group": resourceGitlabGroup(),
"gitlab_project": resourceGitlabProject(),
"gitlab_label": resourceGitlabLabel(),
Expand Down
129 changes: 129 additions & 0 deletions gitlab/resource_gitlab_branch_protection.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
package gitlab

import (
"log"

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

func resourceGitlabBranchProtection() *schema.Resource {
acceptedAccessLevels := make([]string, 0, len(accessLevelID))

for k := range accessLevelID {
acceptedAccessLevels = append(acceptedAccessLevels, k)
}
return &schema.Resource{
Create: resourceGitlabBranchProtectionCreate,
Read: resourceGitlabBranchProtectionRead,
Delete: resourceGitlabBranchProtectionDelete,
Schema: map[string]*schema.Schema{
"project": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"branch": {
Type: schema.TypeString,
ForceNew: true,
Required: true,
},
"merge_access_level": {
Type: schema.TypeString,
ValidateFunc: validateValueFunc(acceptedAccessLevels),
Required: true,
ForceNew: true,
},
"push_access_level": {
Type: schema.TypeString,
ValidateFunc: validateValueFunc(acceptedAccessLevels),
Required: true,
ForceNew: true,
},
},
}
}

func resourceGitlabBranchProtectionCreate(d *schema.ResourceData, meta interface{}) error {
client := meta.(*gitlab.Client)
project := d.Get("project").(string)
branch := gitlab.String(d.Get("branch").(string))
mergeAccessLevel := accessLevelID[d.Get("merge_access_level").(string)]
pushAccessLevel := accessLevelID[d.Get("push_access_level").(string)]

options := &gitlab.ProtectRepositoryBranchesOptions{
Name: branch,
MergeAccessLevel: &mergeAccessLevel,
PushAccessLevel: &pushAccessLevel,
}

log.Printf("[DEBUG] create gitlab branch protection on %v for project %s", options.Name, project)

bp, _, err := client.ProtectedBranches.ProtectRepositoryBranches(project, options)
if err != nil {
// Remove existing branch protection
_, err = client.ProtectedBranches.UnprotectRepositoryBranches(project, *branch)
if err != nil {
return err
}
// Reprotect branch with updated values
bp, _, err = client.ProtectedBranches.ProtectRepositoryBranches(project, options)
if err != nil {
return err
}
}

d.SetId(buildTwoPartID(&project, &bp.Name))

return resourceGitlabBranchProtectionRead(d, meta)
}

func resourceGitlabBranchProtectionRead(d *schema.ResourceData, meta interface{}) error {
client := meta.(*gitlab.Client)
project, branch, err := projectAndBranchFromID(d.Id())
if err != nil {
return err
}

log.Printf("[DEBUG] read gitlab branch protection for project %s, branch %s", project, branch)

pb, response, err := client.ProtectedBranches.GetProtectedBranch(project, branch)
if err != nil {
if response.StatusCode == 404 {
log.Printf("[WARN] removing project branch protection %s from state because it no longer exists in gitlab", branch)
d.SetId("")
return nil
}

return err
}

d.Set("project", project)
d.Set("branch", pb.Name)
d.Set("merge_access_level", pb.MergeAccessLevels[0].AccessLevel)
d.Set("push_access_level", pb.PushAccessLevels[0].AccessLevel)

d.SetId(buildTwoPartID(&project, &pb.Name))

return nil
}

func resourceGitlabBranchProtectionDelete(d *schema.ResourceData, meta interface{}) error {
client := meta.(*gitlab.Client)
project := d.Get("project").(string)
branch := d.Get("branch").(string)

log.Printf("[DEBUG] Delete gitlab protected branch %s for project %s", branch, project)

_, err := client.ProtectedBranches.UnprotectRepositoryBranches(project, branch)
return err
}

func projectAndBranchFromID(id string) (string, string, error) {
project, branch, err := parseTwoPartID(id)

if err != nil {
log.Printf("[WARN] cannot get group member id from input: %v", id)
}
return project, branch, err
}
176 changes: 176 additions & 0 deletions gitlab/resource_gitlab_branch_protection_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
package gitlab

import (
"fmt"
"testing"

"github.com/hashicorp/terraform/helper/acctest"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
"github.com/xanzy/go-gitlab"
)

func TestAccGitlabBranchProtection_basic(t *testing.T) {

var pb gitlab.ProtectedBranch
rInt := acctest.RandInt()

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckGitlabBranchProtectionDestroy,
Steps: []resource.TestStep{
// Create a project and Branch Protection with default options
{
Config: testAccGitlabBranchProtectionConfig(rInt),
Check: resource.ComposeTestCheckFunc(
testAccCheckGitlabBranchProtectionExists("gitlab_branch_protection.BranchProtect", &pb),
testAccCheckGitlabBranchProtectionAttributes(&pb, &testAccGitlabBranchProtectionExpectedAttributes{
Name: fmt.Sprintf("BranchProtect-%d", rInt),
PushAccessLevel: accessLevel[gitlab.DeveloperPermissions],
MergeAccessLevel: accessLevel[gitlab.DeveloperPermissions],
}),
),
},
// Update the Branch Protection
{
Config: testAccGitlabBranchProtectionUpdateConfig(rInt),
Check: resource.ComposeTestCheckFunc(
testAccCheckGitlabBranchProtectionExists("gitlab_branch_protection.BranchProtect", &pb),
testAccCheckGitlabBranchProtectionAttributes(&pb, &testAccGitlabBranchProtectionExpectedAttributes{
Name: fmt.Sprintf("BranchProtect-%d", rInt),
PushAccessLevel: accessLevel[gitlab.MasterPermissions],
MergeAccessLevel: accessLevel[gitlab.MasterPermissions],
}),
),
},
// Update the Branch Protection to get back to initial settings
{
Config: testAccGitlabBranchProtectionConfig(rInt),
Check: resource.ComposeTestCheckFunc(
testAccCheckGitlabBranchProtectionExists("gitlab_branch_protection.BranchProtect", &pb),
testAccCheckGitlabBranchProtectionAttributes(&pb, &testAccGitlabBranchProtectionExpectedAttributes{
Name: fmt.Sprintf("BranchProtect-%d", rInt),
PushAccessLevel: accessLevel[gitlab.DeveloperPermissions],
MergeAccessLevel: accessLevel[gitlab.DeveloperPermissions],
}),
),
},
},
})
}

func testAccCheckGitlabBranchProtectionExists(n string, pb *gitlab.ProtectedBranch) resource.TestCheckFunc {
return func(s *terraform.State) error {
rs, ok := s.RootModule().Resources[n]
if !ok {
return fmt.Errorf("Not Found: %s", n)
}
project, branch, err := projectAndBranchFromID(rs.Primary.ID)
if err != nil {
return fmt.Errorf("Error in Splitting Project and Branch Ids")
}

conn := testAccProvider.Meta().(*gitlab.Client)

pbs, _, err := conn.ProtectedBranches.ListProtectedBranches(project, nil)
if err != nil {
return err
}
for _, gotpb := range pbs {
if gotpb.Name == branch {
*pb = *gotpb
return nil
}
}
return fmt.Errorf("Protected Branch does not exist")
}
}

type testAccGitlabBranchProtectionExpectedAttributes struct {
Name string
PushAccessLevel string
MergeAccessLevel string
}

func testAccCheckGitlabBranchProtectionAttributes(pb *gitlab.ProtectedBranch, want *testAccGitlabBranchProtectionExpectedAttributes) resource.TestCheckFunc {
return func(s *terraform.State) error {
if pb.Name != want.Name {
return fmt.Errorf("got name %q; want %q", pb.Name, want.Name)
}

if pb.PushAccessLevels[0].AccessLevel != accessLevelID[want.PushAccessLevel] {
return fmt.Errorf("got Push access levels %q; want %q", pb.PushAccessLevels[0].AccessLevel, accessLevelID[want.PushAccessLevel])
}

if pb.MergeAccessLevels[0].AccessLevel != accessLevelID[want.MergeAccessLevel] {
return fmt.Errorf("got Merge access levels %q; want %q", pb.MergeAccessLevels[0].AccessLevel, accessLevelID[want.MergeAccessLevel])
}

return nil
}
}

func testAccCheckGitlabBranchProtectionDestroy(s *terraform.State) error {
conn := testAccProvider.Meta().(*gitlab.Client)
var project string
var branch string
for _, rs := range s.RootModule().Resources {
if rs.Type == "gitlab_project" {
project = rs.Primary.ID
} else if rs.Type == "gitlab_branch_protection" {
branch = rs.Primary.ID
}
}

pb, response, err := conn.ProtectedBranches.GetProtectedBranch(project, branch)
if err == nil {
if pb != nil {
return fmt.Errorf("project branch protection %s still exists", branch)
}
}
if response.StatusCode != 404 {
return err
}
return nil
}

func testAccGitlabBranchProtectionConfig(rInt int) string {
return fmt.Sprintf(`
resource "gitlab_project" "foo" {
name = "foo-%d"
description = "Terraform acceptance tests"
# So that acceptance tests can be run in a gitlab organization
# with no billing
visibility_level = "public"
}
resource "gitlab_branch_protection" "BranchProtect" {
project = "${gitlab_project.foo.id}"
branch = "BranchProtect-%d"
push_access_level = "developer"
merge_access_level = "developer"
}
`, rInt, rInt)
}

func testAccGitlabBranchProtectionUpdateConfig(rInt int) string {
return fmt.Sprintf(`
resource "gitlab_project" "foo" {
name = "foo-%d"
description = "Terraform acceptance tests"
# So that acceptance tests can be run in a gitlab organization
# with no billing
visibility_level = "public"
}
resource "gitlab_branch_protection" "BranchProtect" {
project = "${gitlab_project.foo.id}"
branch = "BranchProtect-%d"
push_access_level = "maintainer"
merge_access_level = "maintainer"
}
`, rInt, rInt)
}
34 changes: 34 additions & 0 deletions website/docs/r/branch_protection.html.markdown
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
---
layout: "gitlab"
page_title: "GitLab: gitlab_branch_protection"
sidebar_current: "docs-gitlab-resource-branch_protection"
description: |-
Protects a branch by assigning access levels to it
---

# gitlab\_branch_protection

This resource allows you to protect a specific branch by an access level so that the user with less access level cannot Merge/Push to the branch.

## Example Usage

```hcl
resource "gitlab_branch_protection" "BranchProtect" {
project = "12345"
branch = "BranchProtected"
push_access_level = "developer"
merge_access_level = "developer"
}
```

## Argument Reference

The following arguments are supported:

* `project` - (Required) The id of the project.

* `branch` - (Required) Name of the branch.

* `push_access_level` - (Required) One of five levels of access to the project.

* `merge_access_level` - (Required) One of five levels of access to the project.

0 comments on commit 11c7e32

Please sign in to comment.