Skip to content

Commit f3b926d

Browse files
fandujararmsnyder
andauthored
Adds support for gitlab project badges (#648)
* add project badge support * fix tests and gitlab sdk references * change id to projectid:badgeid and add importer * add gitlab_project_badge documentation * unify basic test and imporState test for project_badge * Change project_badge test order Co-authored-by: Adam Snyder <[email protected]> * remove unnecessary newlines * add project_badge import documentation Co-authored-by: Adam Snyder <[email protected]>
1 parent 021db1c commit f3b926d

File tree

4 files changed

+345
-0
lines changed

4 files changed

+345
-0
lines changed

docs/resources/project_badge.md

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# gitlab\_project\_badge
2+
3+
This resource allows you to create and manage badges for your GitLab projects.
4+
For further information on hooks, consult the [gitlab
5+
documentation](https://docs.gitlab.com/ce/user/project/badges.html).
6+
7+
## Example Usage
8+
9+
```hcl
10+
resource "gitlab_project" "foo" {
11+
name = "foo-project"
12+
}
13+
14+
resource "gitlab_project_badge" "example" {
15+
project = gitlab_project.foo.id
16+
link_url = "https://example.com/badge-123"
17+
image_url = "https://example.com/badge-123.svg"
18+
}
19+
```
20+
21+
## Argument Reference
22+
23+
The following arguments are supported:
24+
25+
* `project` - (Required) The id of the project to add the badge to.
26+
27+
* `link_url` - (Required) The url linked with the badge.
28+
29+
* `image_url` - (Required) The image url which will be presented on project overview.
30+
31+
## Attributes Reference
32+
33+
The resource exports the following attributes:
34+
35+
* `rendered_link_url` - The link_url argument rendered (in case of use of placeholders).
36+
37+
* `rendered_image_url` - The image_url argument rendered (in case of use of placeholders).
38+
39+
## Import
40+
41+
GitLab project badges can be imported using an id made up of `{project_id}:{badge_id}`,
42+
e.g.
43+
44+
```bash
45+
terraform import gitlab_project_badge.foo 1:3
46+
```

gitlab/provider.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ func Provider() terraform.ResourceProvider {
9797
"gitlab_instance_variable": resourceGitlabInstanceVariable(),
9898
"gitlab_project_freeze_period": resourceGitlabProjectFreezePeriod(),
9999
"gitlab_group_share_group": resourceGitlabGroupShareGroup(),
100+
"gitlab_project_badge": resourceGitlabProjectBadge(),
100101
},
101102
}
102103

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
package gitlab
2+
3+
import (
4+
"log"
5+
"strconv"
6+
"strings"
7+
8+
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
9+
gitlab "github.com/xanzy/go-gitlab"
10+
)
11+
12+
func resourceGitlabProjectBadge() *schema.Resource {
13+
return &schema.Resource{
14+
Create: resourceGitlabProjectBadgeCreate,
15+
Read: resourceGitlabProjectBadgeRead,
16+
Update: resourceGitlabProjectBadgeUpdate,
17+
Delete: resourceGitlabProjectBadgeDelete,
18+
Importer: &schema.ResourceImporter{
19+
State: schema.ImportStatePassthrough,
20+
},
21+
22+
Schema: map[string]*schema.Schema{
23+
"project": {
24+
Type: schema.TypeString,
25+
Required: true,
26+
},
27+
"link_url": {
28+
Type: schema.TypeString,
29+
Required: true,
30+
},
31+
"image_url": {
32+
Type: schema.TypeString,
33+
Required: true,
34+
},
35+
"rendered_link_url": {
36+
Type: schema.TypeString,
37+
Computed: true,
38+
},
39+
"rendered_image_url": {
40+
Type: schema.TypeString,
41+
Computed: true,
42+
},
43+
},
44+
}
45+
}
46+
47+
func resourceGitlabProjectBadgeCreate(d *schema.ResourceData, meta interface{}) error {
48+
client := meta.(*gitlab.Client)
49+
projectID := d.Get("project").(string)
50+
options := &gitlab.AddProjectBadgeOptions{
51+
LinkURL: gitlab.String(d.Get("link_url").(string)),
52+
ImageURL: gitlab.String(d.Get("image_url").(string)),
53+
}
54+
55+
log.Printf("[DEBUG] create gitlab project badge %q / %q", *options.LinkURL, *options.ImageURL)
56+
57+
badge, _, err := client.ProjectBadges.AddProjectBadge(projectID, options)
58+
if err != nil {
59+
return err
60+
}
61+
62+
badgeID := strconv.Itoa(badge.ID)
63+
64+
d.SetId(buildTwoPartID(&projectID, &badgeID))
65+
66+
return resourceGitlabProjectBadgeRead(d, meta)
67+
}
68+
69+
func resourceGitlabProjectBadgeRead(d *schema.ResourceData, meta interface{}) error {
70+
client := meta.(*gitlab.Client)
71+
ids := strings.Split(d.Id(), ":")
72+
projectID := ids[0]
73+
badgeID, err := strconv.Atoi(ids[1])
74+
if err != nil {
75+
return err
76+
}
77+
78+
log.Printf("[DEBUG] read gitlab project badge %s/%d", projectID, badgeID)
79+
80+
badge, _, err := client.ProjectBadges.GetProjectBadge(projectID, badgeID)
81+
if err != nil {
82+
return err
83+
}
84+
85+
resourceGitlabProjectBadgeSetToState(d, badge, &projectID)
86+
return nil
87+
}
88+
89+
func resourceGitlabProjectBadgeUpdate(d *schema.ResourceData, meta interface{}) error {
90+
client := meta.(*gitlab.Client)
91+
ids := strings.Split(d.Id(), ":")
92+
projectID := ids[0]
93+
badgeID, err := strconv.Atoi(ids[1])
94+
if err != nil {
95+
return err
96+
}
97+
98+
options := &gitlab.EditProjectBadgeOptions{
99+
LinkURL: gitlab.String(d.Get("link_url").(string)),
100+
ImageURL: gitlab.String(d.Get("image_url").(string)),
101+
}
102+
103+
log.Printf("[DEBUG] update gitlab project badge %s/%d", projectID, badgeID)
104+
105+
_, _, err = client.ProjectBadges.EditProjectBadge(projectID, badgeID, options)
106+
if err != nil {
107+
return err
108+
}
109+
110+
return resourceGitlabProjectBadgeRead(d, meta)
111+
}
112+
113+
func resourceGitlabProjectBadgeDelete(d *schema.ResourceData, meta interface{}) error {
114+
client := meta.(*gitlab.Client)
115+
ids := strings.Split(d.Id(), ":")
116+
projectID := ids[0]
117+
badgeID, err := strconv.Atoi(ids[1])
118+
if err != nil {
119+
return err
120+
}
121+
122+
log.Printf("[DEBUG] Delete gitlab project badge %s/%d", projectID, badgeID)
123+
124+
_, err = client.ProjectBadges.DeleteProjectBadge(projectID, badgeID)
125+
return err
126+
}
127+
128+
func resourceGitlabProjectBadgeSetToState(d *schema.ResourceData, badge *gitlab.ProjectBadge, projectID *string) {
129+
d.Set("link_url", badge.LinkURL)
130+
d.Set("image_url", badge.ImageURL)
131+
d.Set("rendered_link_url", badge.RenderedLinkURL)
132+
d.Set("rendered_image_url", badge.RenderedImageURL)
133+
d.Set("project", projectID)
134+
}
Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
package gitlab
2+
3+
import (
4+
"fmt"
5+
"strconv"
6+
"strings"
7+
"testing"
8+
9+
"github.com/hashicorp/terraform-plugin-sdk/helper/acctest"
10+
"github.com/hashicorp/terraform-plugin-sdk/helper/resource"
11+
"github.com/hashicorp/terraform-plugin-sdk/terraform"
12+
"github.com/xanzy/go-gitlab"
13+
)
14+
15+
func TestAccGitlabProjectBadge_basic(t *testing.T) {
16+
var badge gitlab.ProjectBadge
17+
rInt := acctest.RandInt()
18+
19+
resource.Test(t, resource.TestCase{
20+
PreCheck: func() { testAccPreCheck(t) },
21+
Providers: testAccProviders,
22+
CheckDestroy: testAccCheckGitlabProjectBadgeDestroy,
23+
Steps: []resource.TestStep{
24+
// Create a project and badge
25+
{
26+
Config: testAccGitlabProjectBadgeConfig(rInt),
27+
Check: resource.ComposeTestCheckFunc(
28+
testAccCheckGitlabProjectBadgeExists("gitlab_project_badge.foo", &badge),
29+
testAccCheckGitlabProjectBadgeAttributes(&badge, &testAccGitlabProjectBadgeExpectedAttributes{
30+
LinkURL: fmt.Sprintf("https://example.com/badge-%d", rInt),
31+
ImageURL: fmt.Sprintf("https://example.com/badge-%d.svg", rInt),
32+
}),
33+
),
34+
},
35+
// Test ImportState
36+
{
37+
ResourceName: "gitlab_project_badge.foo",
38+
ImportState: true,
39+
ImportStateVerify: true,
40+
},
41+
// Update the project badge
42+
{
43+
Config: testAccGitlabProjectBadgeUpdateConfig(rInt),
44+
Check: resource.ComposeTestCheckFunc(
45+
testAccCheckGitlabProjectBadgeExists("gitlab_project_badge.foo", &badge),
46+
testAccCheckGitlabProjectBadgeAttributes(&badge, &testAccGitlabProjectBadgeExpectedAttributes{
47+
LinkURL: fmt.Sprintf("https://example.com/badge-%d", rInt),
48+
ImageURL: fmt.Sprintf("https://example.com/badge-%d.svg", rInt),
49+
}),
50+
),
51+
},
52+
},
53+
})
54+
}
55+
56+
func testAccCheckGitlabProjectBadgeExists(n string, badge *gitlab.ProjectBadge) resource.TestCheckFunc {
57+
return func(s *terraform.State) error {
58+
rs, ok := s.RootModule().Resources[n]
59+
if !ok {
60+
return fmt.Errorf("Not Found: %s", n)
61+
}
62+
63+
splitID := strings.Split(rs.Primary.ID, ":")
64+
65+
badgeID, err := strconv.Atoi(splitID[len(splitID)-1])
66+
if err != nil {
67+
return err
68+
}
69+
repoName := rs.Primary.Attributes["project"]
70+
if repoName == "" {
71+
return fmt.Errorf("No project ID is set")
72+
}
73+
74+
conn := testAccProvider.Meta().(*gitlab.Client)
75+
76+
gotBadge, _, err := conn.ProjectBadges.GetProjectBadge(repoName, badgeID)
77+
if err != nil {
78+
return err
79+
}
80+
*badge = *gotBadge
81+
return nil
82+
}
83+
}
84+
85+
type testAccGitlabProjectBadgeExpectedAttributes struct {
86+
LinkURL string
87+
ImageURL string
88+
}
89+
90+
func testAccCheckGitlabProjectBadgeAttributes(badge *gitlab.ProjectBadge, want *testAccGitlabProjectBadgeExpectedAttributes) resource.TestCheckFunc {
91+
return func(s *terraform.State) error {
92+
if badge.LinkURL != want.LinkURL {
93+
return fmt.Errorf("got link_url %q; want %q", badge.LinkURL, want.LinkURL)
94+
}
95+
96+
if badge.ImageURL != want.ImageURL {
97+
return fmt.Errorf("got image_url %s; want %s", badge.ImageURL, want.ImageURL)
98+
}
99+
100+
return nil
101+
}
102+
}
103+
104+
func testAccCheckGitlabProjectBadgeDestroy(s *terraform.State) error {
105+
conn := testAccProvider.Meta().(*gitlab.Client)
106+
107+
for _, rs := range s.RootModule().Resources {
108+
if rs.Type != "gitlab_project" {
109+
continue
110+
}
111+
112+
gotRepo, resp, err := conn.Projects.GetProject(rs.Primary.ID, nil)
113+
if err == nil {
114+
if gotRepo != nil && fmt.Sprintf("%d", gotRepo.ID) == rs.Primary.ID {
115+
if gotRepo.MarkedForDeletionAt == nil {
116+
return fmt.Errorf("Repository still exists")
117+
}
118+
}
119+
}
120+
if resp.StatusCode != 404 {
121+
return err
122+
}
123+
return nil
124+
}
125+
return nil
126+
}
127+
128+
func testAccGitlabProjectBadgeConfig(rInt int) string {
129+
return fmt.Sprintf(`
130+
resource "gitlab_project" "foo" {
131+
name = "foo-%d"
132+
description = "Terraform acceptance tests"
133+
134+
# So that acceptance tests can be run in a gitlab organization
135+
# with no billing
136+
visibility_level = "public"
137+
}
138+
139+
resource "gitlab_project_badge" "foo" {
140+
project = "${gitlab_project.foo.id}"
141+
link_url = "https://example.com/badge-%d"
142+
image_url = "https://example.com/badge-%d.svg"
143+
}
144+
`, rInt, rInt, rInt)
145+
}
146+
147+
func testAccGitlabProjectBadgeUpdateConfig(rInt int) string {
148+
return fmt.Sprintf(`
149+
resource "gitlab_project" "foo" {
150+
name = "foo-%d"
151+
description = "Terraform acceptance tests"
152+
153+
# So that acceptance tests can be run in a gitlab organization
154+
# with no billing
155+
visibility_level = "public"
156+
}
157+
158+
resource "gitlab_project_badge" "foo" {
159+
project = "${gitlab_project.foo.id}"
160+
link_url = "https://example.com/badge-%d"
161+
image_url = "https://example.com/badge-%d.svg"
162+
}
163+
`, rInt, rInt, rInt)
164+
}

0 commit comments

Comments
 (0)