Skip to content

Commit

Permalink
resource/gitlab_project_approval_rule: fix potential accidential dest…
Browse files Browse the repository at this point in the history
…roy of resource if not in first page

This fixes a potential bug that the resource is marked for destroy after a read,
because it was not found on the first page. Pagination was not implemented.
However, there exist a specific API to get a single project-level approval rule.
I have implemented it in go-gitlab:

* xanzy/go-gitlab#1410

After it is released, we should be able to just rebase and LGTM ;)
  • Loading branch information
timofurrer committed Mar 12, 2022
1 parent 49db985 commit 36e9b75
Showing 1 changed file with 11 additions and 33 deletions.
44 changes: 11 additions & 33 deletions internal/provider/resource_gitlab_project_approval_rule.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,21 +119,28 @@ func resourceGitlabProjectApprovalRuleCreate(ctx context.Context, d *schema.Reso
func resourceGitlabProjectApprovalRuleRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
log.Printf("[DEBUG] read gitlab project-level rule %s", d.Id())

projectID, _, err := parseTwoPartID(d.Id())
projectID, parsedRuleID, err := parseTwoPartID(d.Id())
if err != nil {
return diag.FromErr(err)
}
d.Set("project", projectID)
ruleID, err := strconv.Atoi(parsedRuleID)
if err != nil {
return diag.FromErr(err)
}

client := meta.(*gitlab.Client)

rule, err := getApprovalRuleByID(ctx, meta.(*gitlab.Client), d.Id())
rule, _, err := client.Projects.GetProjectApprovalRule(projectID, ruleID, gitlab.WithContext(ctx))
if err != nil {
if errors.Is(err, errApprovalRuleNotFound) {
if is404(err) {
log.Printf("[DEBUG] no project-level rule %s found, removing from state", d.Id())
d.SetId("")
return nil
}
return diag.FromErr(err)
}

d.Set("project", projectID)
d.Set("name", rule.Name)
d.Set("approvals_required", rule.ApprovalsRequired)
d.Set("rule_type", rule.RuleType)
Expand Down Expand Up @@ -207,35 +214,6 @@ func resourceGitlabProjectApprovalRuleDelete(ctx context.Context, d *schema.Reso
return nil
}

// getApprovalRuleByID checks the list of rules and finds the one that matches our rule ID.
func getApprovalRuleByID(ctx context.Context, client *gitlab.Client, id string) (*gitlab.ProjectApprovalRule, error) {
projectID, ruleID, err := parseTwoPartID(id)
if err != nil {
return nil, err
}

ruleIDInt, err := strconv.Atoi(ruleID)
if err != nil {
return nil, err
}

log.Printf("[DEBUG] read approval rules for project %s", projectID)

rules, _, err := client.Projects.GetProjectApprovalRules(projectID, gitlab.WithContext(ctx))
if err != nil {
return nil, err
}

for _, r := range rules {
if r.ID == ruleIDInt {
log.Printf("[DEBUG] found project-level rule %+v", r)
return r, nil
}
}

return nil, errApprovalRuleNotFound
}

// flattenApprovalRuleUserIDs flattens a list of approval user ids into a list
// of ints for storage in state.
func flattenApprovalRuleUserIDs(users []*gitlab.BasicUser) []int {
Expand Down

0 comments on commit 36e9b75

Please sign in to comment.