Skip to content

Commit 720cb4f

Browse files
authored
Merge pull request #954 from timofurrer/cleanup/get-single-label
Use specific GET API instead of list for labels
2 parents 6c8d6b0 + eafe112 commit 720cb4f

File tree

6 files changed

+90
-194
lines changed

6 files changed

+90
-194
lines changed

docs/resources/label.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,4 +46,11 @@ resource "gitlab_label" "devops_create" {
4646
- **description** (String) The description of the label.
4747
- **id** (String) The ID of this resource.
4848

49+
## Import
4950

51+
Import is supported using the following syntax:
52+
53+
```shell
54+
# Gitlab labels can be imported using an id made up of `{project_id}:{group_label_id}`, e.g.
55+
terraform import gitlab_label.example 12345:fixme
56+
```
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# Gitlab labels can be imported using an id made up of `{project_id}:{group_label_id}`, e.g.
2+
terraform import gitlab_label.example 12345:fixme

internal/provider/resource_gitlab_group_label.go

Lines changed: 10 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,6 @@ func resourceGitlabGroupLabelCreate(ctx context.Context, d *schema.ResourceData,
7272
}
7373

7474
d.SetId(label.Name)
75-
7675
return resourceGitlabGroupLabelRead(ctx, d, meta)
7776
}
7877

@@ -82,27 +81,18 @@ func resourceGitlabGroupLabelRead(ctx context.Context, d *schema.ResourceData, m
8281
labelName := d.Id()
8382
log.Printf("[DEBUG] read gitlab group label %s/%s", group, labelName)
8483

85-
page := 1
86-
labelsLen := 0
87-
for page == 1 || labelsLen != 0 {
88-
labels, _, err := client.GroupLabels.ListGroupLabels(group, &gitlab.ListGroupLabelsOptions{ListOptions: gitlab.ListOptions{Page: page}}, gitlab.WithContext(ctx))
89-
if err != nil {
90-
return diag.FromErr(err)
91-
}
92-
for _, label := range labels {
93-
if label.Name == labelName {
94-
d.Set("description", label.Description)
95-
d.Set("color", label.Color)
96-
d.Set("name", label.Name)
97-
return nil
98-
}
84+
label, _, err := client.GroupLabels.GetGroupLabel(group, labelName, gitlab.WithContext(ctx))
85+
if err != nil {
86+
if is404(err) {
87+
log.Printf("[DEBUG] failed to read gitlab label %s/%s, removing from state", group, labelName)
88+
d.SetId("")
89+
return nil
9990
}
100-
labelsLen = len(labels)
101-
page = page + 1
91+
return diag.FromErr(err)
10292
}
103-
104-
log.Printf("[DEBUG] failed to read gitlab label %s/%s", group, labelName)
105-
d.SetId("")
93+
d.Set("description", label.Description)
94+
d.Set("color", label.Color)
95+
d.Set("name", label.Name)
10696
return nil
10797
}
10898

internal/provider/resource_gitlab_group_label_test.go

Lines changed: 2 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -53,53 +53,8 @@ func TestAccGitlabGroupLabel_basic(t *testing.T) {
5353
),
5454
},
5555
{
56-
Config: testAccGitlabGroupLabelLargeConfig(rInt),
57-
Check: resource.ComposeTestCheckFunc(
58-
testAccCheckGitlabGroupLabelExists("gitlab_group_label.fixme.20", &label),
59-
testAccCheckGitlabGroupLabelExists("gitlab_group_label.fixme.30", &label),
60-
testAccCheckGitlabGroupLabelExists("gitlab_group_label.fixme.40", &label),
61-
testAccCheckGitlabGroupLabelExists("gitlab_group_label.fixme.10", &label),
62-
testAccCheckGitlabGroupLabelAttributes(&label, &testAccGitlabGroupLabelExpectedAttributes{
63-
Name: "FIXME11",
64-
Color: "#ffcc00",
65-
Description: "fix this test",
66-
}),
67-
),
68-
},
69-
{
70-
Config: testAccGitlabGroupLabelUpdateLargeConfig(rInt),
71-
Check: resource.ComposeTestCheckFunc(
72-
testAccCheckGitlabGroupLabelExists("gitlab_group_label.fixme.20", &label),
73-
testAccCheckGitlabGroupLabelExists("gitlab_group_label.fixme.30", &label),
74-
testAccCheckGitlabGroupLabelExists("gitlab_group_label.fixme.40", &label),
75-
testAccCheckGitlabGroupLabelExists("gitlab_group_label.fixme.10", &label),
76-
testAccCheckGitlabGroupLabelAttributes(&label, &testAccGitlabGroupLabelExpectedAttributes{
77-
Name: "FIXME11",
78-
Color: "#ff0000",
79-
Description: "red label",
80-
}),
81-
),
82-
},
83-
},
84-
})
85-
}
86-
87-
// lintignore: AT002 // TODO: Resolve this tfproviderlint issue
88-
func TestAccGitlabGroupLabel_import(t *testing.T) {
89-
rInt := acctest.RandInt()
90-
resourceName := "gitlab_group_label.fixme"
91-
92-
resource.Test(t, resource.TestCase{
93-
PreCheck: func() { testAccPreCheck(t) },
94-
ProviderFactories: providerFactories,
95-
CheckDestroy: testAccCheckGitlabGroupLabelDestroy,
96-
Steps: []resource.TestStep{
97-
{
98-
Config: testAccGitlabGroupLabelConfig(rInt),
99-
},
100-
{
101-
ResourceName: resourceName,
102-
ImportStateIdFunc: getGroupLabelImportID(resourceName),
56+
ResourceName: "gitlab_group_label.fixme",
57+
ImportStateIdFunc: getGroupLabelImportID("gitlab_group_label.fixme"),
10358
ImportState: true,
10459
ImportStateVerify: true,
10560
},
@@ -235,41 +190,3 @@ resource "gitlab_group_label" "fixme" {
235190
}
236191
`, rInt, rInt, rInt)
237192
}
238-
239-
func testAccGitlabGroupLabelLargeConfig(rInt int) string {
240-
return fmt.Sprintf(`
241-
resource "gitlab_group" "foo" {
242-
name = "foo-%d"
243-
path = "foo-%d"
244-
description = "Terraform acceptance tests"
245-
visibility_level = "public"
246-
}
247-
248-
resource "gitlab_group_label" "fixme" {
249-
group = "${gitlab_group.foo.id}"
250-
name = format("FIXME%%02d", count.index+1)
251-
count = 100
252-
color = "#ffcc00"
253-
description = "fix this test"
254-
}
255-
`, rInt, rInt)
256-
}
257-
258-
func testAccGitlabGroupLabelUpdateLargeConfig(rInt int) string {
259-
return fmt.Sprintf(`
260-
resource "gitlab_group" "foo" {
261-
name = "foo-%d"
262-
path = "foo-%d"
263-
description = "Terraform acceptance tests"
264-
visibility_level = "public"
265-
}
266-
267-
resource "gitlab_group_label" "fixme" {
268-
group = "${gitlab_group.foo.id}"
269-
name = format("FIXME%%02d", count.index+1)
270-
count = 99
271-
color = "#ff0000"
272-
description = "red label"
273-
}
274-
`, rInt, rInt)
275-
}

internal/provider/resource_gitlab_label.go

Lines changed: 44 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,17 @@ package provider
22

33
import (
44
"context"
5+
"fmt"
56
"log"
7+
"strconv"
8+
"strings"
69

710
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
811
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
912
gitlab "github.com/xanzy/go-gitlab"
1013
)
1114

1215
var _ = registerResource("gitlab_label", func() *schema.Resource {
13-
// lintignore: XR002 // TODO: Resolve this tfproviderlint issue
1416
return &schema.Resource{
1517
Description: `The ` + "`" + `gitlab_label` + "`" + ` resource allows to manage the lifecycle of a project label.
1618
@@ -20,6 +22,12 @@ var _ = registerResource("gitlab_label", func() *schema.Resource {
2022
ReadContext: resourceGitlabLabelRead,
2123
UpdateContext: resourceGitlabLabelUpdate,
2224
DeleteContext: resourceGitlabLabelDelete,
25+
// FIXME: this importer sucks a little, but we can't use a passthrough importer, because
26+
// the resource id is flawed and we don't want to break backwards-compatibility.
27+
// We cannot have the same label in two different projects as of now, ...
28+
Importer: &schema.ResourceImporter{
29+
StateContext: resourceGitlabLabelImporter,
30+
},
2331

2432
Schema: map[string]*schema.Schema{
2533
"project": {
@@ -77,27 +85,19 @@ func resourceGitlabLabelRead(ctx context.Context, d *schema.ResourceData, meta i
7785
labelName := d.Id()
7886
log.Printf("[DEBUG] read gitlab label %s/%s", project, labelName)
7987

80-
page := 1
81-
labelsLen := 0
82-
for page == 1 || labelsLen != 0 {
83-
labels, _, err := client.Labels.ListLabels(project, &gitlab.ListLabelsOptions{ListOptions: gitlab.ListOptions{Page: page}}, gitlab.WithContext(ctx))
84-
if err != nil {
85-
return diag.FromErr(err)
86-
}
87-
for _, label := range labels {
88-
if label.Name == labelName {
89-
d.Set("description", label.Description)
90-
d.Set("color", label.Color)
91-
d.Set("name", label.Name)
92-
return nil
93-
}
88+
label, _, err := client.Labels.GetLabel(project, labelName, gitlab.WithContext(ctx))
89+
if err != nil {
90+
if is404(err) {
91+
log.Printf("[DEBUG] failed to read gitlab label %s/%s", project, labelName)
92+
d.SetId("")
93+
return nil
9494
}
95-
labelsLen = len(labels)
96-
page = page + 1
95+
return diag.FromErr(err)
9796
}
9897

99-
log.Printf("[DEBUG] failed to read gitlab label %s/%s", project, labelName)
100-
d.SetId("")
98+
d.Set("description", label.Description)
99+
d.Set("color", label.Color)
100+
d.Set("name", label.Name)
101101
return nil
102102
}
103103

@@ -138,3 +138,28 @@ func resourceGitlabLabelDelete(ctx context.Context, d *schema.ResourceData, meta
138138

139139
return nil
140140
}
141+
142+
func resourceGitlabLabelImporter(ctx context.Context, d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) {
143+
client := meta.(*gitlab.Client)
144+
parts := strings.SplitN(d.Id(), ":", 2)
145+
if len(parts) != 2 {
146+
return nil, fmt.Errorf("invalid label id (should be <project ID>.<label name>): %s", d.Id())
147+
}
148+
149+
d.SetId(parts[1])
150+
project, _, err := client.Projects.GetProject(parts[0], nil)
151+
if err != nil {
152+
return nil, err
153+
}
154+
155+
if err := d.Set("project", strconv.Itoa(project.ID)); err != nil {
156+
return nil, err
157+
}
158+
159+
diagnostic := resourceGitlabLabelRead(ctx, d, meta)
160+
if diagnostic.HasError() {
161+
return nil, fmt.Errorf("failed to read project label %s: %s", d.Id(), diagnostic[0].Summary)
162+
}
163+
164+
return []*schema.ResourceData{d}, nil
165+
}

internal/provider/resource_gitlab_label_test.go

Lines changed: 25 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -55,40 +55,37 @@ func TestAccGitlabLabel_basic(t *testing.T) {
5555
}),
5656
),
5757
},
58-
// Create a project and lots of labels with default options
58+
// Verify Import
5959
{
60-
Config: testAccGitlabLabelLargeConfig(rInt),
61-
Check: resource.ComposeTestCheckFunc(
62-
testAccCheckGitlabLabelExists("gitlab_label.fixme.20", &label),
63-
testAccCheckGitlabLabelExists("gitlab_label.fixme.30", &label),
64-
testAccCheckGitlabLabelExists("gitlab_label.fixme.40", &label),
65-
testAccCheckGitlabLabelExists("gitlab_label.fixme.10", &label),
66-
testAccCheckGitlabLabelAttributes(&label, &testAccGitlabLabelExpectedAttributes{
67-
Name: "FIXME11",
68-
Color: "#ffcc00",
69-
Description: "fix this test",
70-
}),
71-
),
72-
},
73-
// Update the lots of labels to change the parameters
74-
{
75-
Config: testAccGitlabLabelUpdateLargeConfig(rInt),
76-
Check: resource.ComposeTestCheckFunc(
77-
testAccCheckGitlabLabelExists("gitlab_label.fixme.20", &label),
78-
testAccCheckGitlabLabelExists("gitlab_label.fixme.30", &label),
79-
testAccCheckGitlabLabelExists("gitlab_label.fixme.40", &label),
80-
testAccCheckGitlabLabelExists("gitlab_label.fixme.10", &label),
81-
testAccCheckGitlabLabelAttributes(&label, &testAccGitlabLabelExpectedAttributes{
82-
Name: "FIXME11",
83-
Color: "#ff0000",
84-
Description: "red label",
85-
}),
86-
),
60+
ResourceName: "gitlab_label.fixme",
61+
ImportStateIdFunc: getLabelImportID("gitlab_label.fixme"),
62+
ImportState: true,
63+
ImportStateVerify: true,
8764
},
8865
},
8966
})
9067
}
9168

69+
func getLabelImportID(n string) resource.ImportStateIdFunc {
70+
return func(s *terraform.State) (string, error) {
71+
rs, ok := s.RootModule().Resources[n]
72+
if !ok {
73+
return "", fmt.Errorf("Not Found: %s", n)
74+
}
75+
76+
labelID := rs.Primary.ID
77+
if labelID == "" {
78+
return "", fmt.Errorf("No label key ID is set")
79+
}
80+
projectID := rs.Primary.Attributes["project"]
81+
if projectID == "" {
82+
return "", fmt.Errorf("No project ID is set")
83+
}
84+
85+
return fmt.Sprintf("%s:%s", projectID, labelID), nil
86+
}
87+
}
88+
9289
func testAccCheckGitlabLabelExists(n string, label *gitlab.Label) resource.TestCheckFunc {
9390
return func(s *terraform.State) error {
9491
rs, ok := s.RootModule().Resources[n]
@@ -201,45 +198,3 @@ resource "gitlab_label" "fixme" {
201198
}
202199
`, rInt, rInt)
203200
}
204-
205-
func testAccGitlabLabelLargeConfig(rInt int) string {
206-
return fmt.Sprintf(`
207-
resource "gitlab_project" "foo" {
208-
name = "foo-%d"
209-
description = "Terraform acceptance tests"
210-
211-
# So that acceptance tests can be run in a gitlab organization
212-
# with no billing
213-
visibility_level = "public"
214-
}
215-
216-
resource "gitlab_label" "fixme" {
217-
project = "${gitlab_project.foo.id}"
218-
name = format("FIXME%%02d", count.index+1)
219-
count = 100
220-
color = "#ffcc00"
221-
description = "fix this test"
222-
}
223-
`, rInt)
224-
}
225-
226-
func testAccGitlabLabelUpdateLargeConfig(rInt int) string {
227-
return fmt.Sprintf(`
228-
resource "gitlab_project" "foo" {
229-
name = "foo-%d"
230-
description = "Terraform acceptance tests"
231-
232-
# So that acceptance tests can be run in a gitlab organization
233-
# with no billing
234-
visibility_level = "public"
235-
}
236-
237-
resource "gitlab_label" "fixme" {
238-
project = "${gitlab_project.foo.id}"
239-
name = format("FIXME%%02d", count.index+1)
240-
count = 99
241-
color = "#ff0000"
242-
description = "red label"
243-
}
244-
`, rInt)
245-
}

0 commit comments

Comments
 (0)