-
Notifications
You must be signed in to change notification settings - Fork 319
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'more-resources' of gh:stakater/terraform-provider-gitlab
- Loading branch information
Showing
4 changed files
with
340 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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. |