Skip to content

Commit e75bcb3

Browse files
authored
Merge pull request #963 from Moon1706/feature/tags
Add data source gitlab_project_tags
2 parents d8c97a0 + c8b11c4 commit e75bcb3

File tree

9 files changed

+388
-107
lines changed

9 files changed

+388
-107
lines changed

docs/data-sources/project_tag.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,8 @@ data "gitlab_project_tag" "foo" {
4343

4444
### Read-Only
4545

46-
- **commit** (Set of Object) The commit associated with the tag ref. (see [below for nested schema](#nestedatt--commit))
47-
- **message** (String) Creates annotated tag.
46+
- **commit** (Set of Object) The commit associated with the tag. (see [below for nested schema](#nestedatt--commit))
47+
- **message** (String) The message of the annotated tag.
4848
- **protected** (Boolean) Bool, true if tag has tag protection.
4949
- **release** (Set of Object) The release associated with the tag. (see [below for nested schema](#nestedatt--release))
5050
- **target** (String) The unique id assigned to the commit by Gitlab.

docs/data-sources/project_tags.md

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
---
2+
# generated by https://github.com/hashicorp/terraform-plugin-docs
3+
page_title: "gitlab_project_tags Data Source - terraform-provider-gitlab"
4+
subcategory: ""
5+
description: |-
6+
The gitlab_project_tags data source allows details of project tags to be retrieved by some search criteria.
7+
Upstream API: GitLab REST API docs https://docs.gitlab.com/ee/api/tags.html#list-project-repository-tags
8+
---
9+
10+
# gitlab_project_tags (Data Source)
11+
12+
The `gitlab_project_tags` data source allows details of project tags to be retrieved by some search criteria.
13+
14+
**Upstream API**: [GitLab REST API docs](https://docs.gitlab.com/ee/api/tags.html#list-project-repository-tags)
15+
16+
## Example Usage
17+
18+
```terraform
19+
# By project ID
20+
data "gitlab_project_tags" "example" {
21+
project = "12345"
22+
}
23+
24+
# By project full path
25+
data "gitlab_project_tags" "example" {
26+
project = "foo/bar"
27+
}
28+
```
29+
30+
<!-- schema generated by tfplugindocs -->
31+
## Schema
32+
33+
### Required
34+
35+
- **project** (String) The ID or URL-encoded path of the project owned by the authenticated user.
36+
37+
### Optional
38+
39+
- **id** (String) The ID of this resource.
40+
- **order_by** (String) Return tags ordered by `name` or `updated` fields. Default is `updated`.
41+
- **search** (String) Return list of tags matching the search criteria. You can use `^term` and `term$` to find tags that begin and end with `term` respectively. No other regular expressions are supported.
42+
- **sort** (String) Return tags sorted in `asc` or `desc` order. Default is `desc`.
43+
44+
### Read-Only
45+
46+
- **tags** (List of Object) List of repository tags from a project. (see [below for nested schema](#nestedatt--tags))
47+
48+
<a id="nestedatt--tags"></a>
49+
### Nested Schema for `tags`
50+
51+
Read-Only:
52+
53+
- **commit** (Set of Object) (see [below for nested schema](#nestedobjatt--tags--commit))
54+
- **message** (String)
55+
- **name** (String)
56+
- **protected** (Boolean)
57+
- **release** (Set of Object) (see [below for nested schema](#nestedobjatt--tags--release))
58+
- **target** (String)
59+
60+
<a id="nestedobjatt--tags--commit"></a>
61+
### Nested Schema for `tags.commit`
62+
63+
Read-Only:
64+
65+
- **author_email** (String)
66+
- **author_name** (String)
67+
- **authored_date** (String)
68+
- **committed_date** (String)
69+
- **committer_email** (String)
70+
- **committer_name** (String)
71+
- **id** (String)
72+
- **message** (String)
73+
- **parent_ids** (Set of String)
74+
- **short_id** (String)
75+
- **title** (String)
76+
77+
78+
<a id="nestedobjatt--tags--release"></a>
79+
### Nested Schema for `tags.release`
80+
81+
Read-Only:
82+
83+
- **description** (String)
84+
- **tag_name** (String)
85+
86+

docs/resources/project_tag.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ resource "gitlab_project_tag" "example" {
4242
### Optional
4343

4444
- **id** (String) The ID of this resource.
45-
- **message** (String) Creates annotated tag.
45+
- **message** (String) The message of the annotated tag.
4646

4747
### Read-Only
4848

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# By project ID
2+
data "gitlab_project_tags" "example" {
3+
project = "12345"
4+
}
5+
6+
# By project full path
7+
data "gitlab_project_tags" "example" {
8+
project = "foo/bar"
9+
}

internal/provider/data_source_gitlab_project_tag.go

Lines changed: 9 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -16,47 +16,16 @@ var _ = registerDataSource("gitlab_project_tag", func() *schema.Resource {
1616
**Upstream API**: [GitLab API docs](https://docs.gitlab.com/ee/api/tags.html)`,
1717

1818
ReadContext: dataSourceGitlabProjectTagRead,
19-
Schema: map[string]*schema.Schema{
20-
"name": {
21-
Description: "The name of a tag.",
22-
Type: schema.TypeString,
23-
Required: true,
19+
Schema: constructSchema(
20+
datasourceSchemaFromResourceSchema(gitlabProjectTagGetSchema(), "name"),
21+
map[string]*schema.Schema{
22+
"project": {
23+
Description: "The ID or URL-encoded path of the project owned by the authenticated user.",
24+
Type: schema.TypeString,
25+
Required: true,
26+
},
2427
},
25-
"project": {
26-
Description: "The ID or URL-encoded path of the project owned by the authenticated user.",
27-
Type: schema.TypeString,
28-
Required: true,
29-
},
30-
"message": {
31-
Description: "Creates annotated tag.",
32-
Type: schema.TypeString,
33-
Computed: true,
34-
},
35-
"protected": {
36-
Description: "Bool, true if tag has tag protection.",
37-
Type: schema.TypeBool,
38-
Computed: true,
39-
},
40-
"target": {
41-
Description: "The unique id assigned to the commit by Gitlab.",
42-
Type: schema.TypeString,
43-
Computed: true,
44-
},
45-
"release": {
46-
Description: "The release associated with the tag.",
47-
Type: schema.TypeSet,
48-
Computed: true,
49-
Set: schema.HashResource(releaseNoteSchema),
50-
Elem: releaseNoteSchema,
51-
},
52-
"commit": {
53-
Description: "The commit associated with the tag ref.",
54-
Type: schema.TypeSet,
55-
Computed: true,
56-
Set: schema.HashResource(commitSchema),
57-
Elem: commitSchema,
58-
},
59-
},
28+
),
6029
}
6130
})
6231

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
package provider
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"log"
7+
8+
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
9+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
10+
"github.com/mitchellh/hashstructure"
11+
"github.com/xanzy/go-gitlab"
12+
)
13+
14+
var _ = registerDataSource("gitlab_project_tags", func() *schema.Resource {
15+
return &schema.Resource{
16+
Description: `The ` + "`gitlab_project_tags`" + ` data source allows details of project tags to be retrieved by some search criteria.
17+
18+
**Upstream API**: [GitLab REST API docs](https://docs.gitlab.com/ee/api/tags.html#list-project-repository-tags)`,
19+
20+
ReadContext: dataSourceGitlabProjectTagsRead,
21+
Schema: map[string]*schema.Schema{
22+
"project": {
23+
Description: "The ID or URL-encoded path of the project owned by the authenticated user.",
24+
Type: schema.TypeString,
25+
Required: true,
26+
},
27+
"order_by": {
28+
Description: "Return tags ordered by `name` or `updated` fields. Default is `updated`.",
29+
Type: schema.TypeString,
30+
Optional: true,
31+
},
32+
"sort": {
33+
Description: "Return tags sorted in `asc` or `desc` order. Default is `desc`.",
34+
Type: schema.TypeString,
35+
Optional: true,
36+
},
37+
"search": {
38+
Description: "Return list of tags matching the search criteria. You can use `^term` and `term$` to find tags that begin and end with `term` respectively. No other regular expressions are supported.",
39+
Type: schema.TypeString,
40+
Optional: true,
41+
},
42+
"tags": {
43+
Description: "List of repository tags from a project.",
44+
Type: schema.TypeList,
45+
Computed: true,
46+
Elem: &schema.Resource{
47+
Schema: datasourceSchemaFromResourceSchema(gitlabProjectTagGetSchema()),
48+
},
49+
},
50+
},
51+
}
52+
})
53+
54+
func dataSourceGitlabProjectTagsRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
55+
client := meta.(*gitlab.Client)
56+
57+
project := d.Get("project").(string)
58+
options := gitlab.ListTagsOptions{
59+
ListOptions: gitlab.ListOptions{
60+
PerPage: 20,
61+
Page: 1,
62+
},
63+
}
64+
65+
if v, ok := d.GetOk("order_by"); ok {
66+
options.OrderBy = gitlab.String(v.(string))
67+
}
68+
69+
if v, ok := d.GetOk("sort"); ok {
70+
options.Sort = gitlab.String(v.(string))
71+
}
72+
73+
if v, ok := d.GetOk("search"); ok {
74+
options.Search = gitlab.String(v.(string))
75+
}
76+
77+
optionsHash, err := hashstructure.Hash(&options, nil)
78+
if err != nil {
79+
return diag.FromErr(err)
80+
}
81+
82+
var tags []*gitlab.Tag
83+
for options.Page != 0 {
84+
paginatedTags, resp, err := client.Tags.ListTags(project, &options, gitlab.WithContext(ctx))
85+
if err != nil {
86+
return diag.FromErr(err)
87+
}
88+
89+
tags = append(tags, paginatedTags...)
90+
options.Page = resp.NextPage
91+
}
92+
93+
log.Printf("[DEBUG] get gitlab tags from project: %s", project)
94+
d.SetId(fmt.Sprintf("%s:%d", project, optionsHash))
95+
d.Set("project", project)
96+
d.Set("order_by", options.OrderBy)
97+
d.Set("sort", options.Sort)
98+
d.Set("search", options.Search)
99+
if err = d.Set("tags", flattenDataTags(tags)); err != nil {
100+
return diag.Errorf("Failed to set tags to state: %v", err)
101+
}
102+
return nil
103+
}
104+
105+
func flattenDataTags(tags []*gitlab.Tag) (values []map[string]interface{}) {
106+
for _, tag := range tags {
107+
values = append(values, map[string]interface{}{
108+
"commit": flattenCommit(tag.Commit),
109+
"release": flattenReleaseNote(tag.Release),
110+
"name": tag.Name,
111+
"target": tag.Target,
112+
"message": tag.Message,
113+
"protected": tag.Protected,
114+
})
115+
}
116+
return values
117+
}
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
package provider
2+
3+
import (
4+
"fmt"
5+
"testing"
6+
7+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
8+
"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
9+
)
10+
11+
func TestAccDataGitlabProjectTags_basic(t *testing.T) {
12+
testAccCheck(t)
13+
countTags := 3
14+
project := testAccCreateProject(t)
15+
16+
resource.Test(t, resource.TestCase{
17+
PreCheck: func() { testAccPreCheck(t) },
18+
ProviderFactories: providerFactories,
19+
Steps: []resource.TestStep{
20+
{
21+
Config: testAccDataGitlabProjectTags(countTags, project.PathWithNamespace),
22+
Check: resource.ComposeTestCheckFunc(
23+
testAccDataSourceGitlabProjectTags("gitlab_project_tag.foo", "data.gitlab_project_tags.foo", countTags),
24+
),
25+
},
26+
},
27+
})
28+
}
29+
30+
func testAccDataSourceGitlabProjectTags(src string, n string, countTags int) resource.TestCheckFunc {
31+
return func(s *terraform.State) error {
32+
testAttributes := []string{
33+
"commit",
34+
"release",
35+
"name",
36+
"message",
37+
"protected",
38+
"target",
39+
}
40+
41+
for numberTag := range make([]int, countTags) {
42+
search := s.RootModule().Resources[n]
43+
searchAttrs := search.Primary.Attributes
44+
45+
tag := s.RootModule().Resources[fmt.Sprintf("%s.%d", src, numberTag)]
46+
tagAttrs := tag.Primary.Attributes
47+
48+
for _, attribute := range testAttributes {
49+
tagAttr := tagAttrs[attribute]
50+
searchAttr := searchAttrs[fmt.Sprintf("tags.%d.%s", numberTag, attribute)]
51+
if searchAttr != tagAttr {
52+
return fmt.Errorf("Expected the tag `%s` with parameter `%s` to be: `%s`, but got: `%s`", tagAttrs["name"], attribute, tagAttr, searchAttr)
53+
}
54+
}
55+
}
56+
57+
return nil
58+
}
59+
}
60+
61+
func testAccDataGitlabProjectTags(countTags int, project string) string {
62+
return fmt.Sprintf(`
63+
%s
64+
data "gitlab_project_tags" "foo" {
65+
project = "%s"
66+
order_by = "name"
67+
sort = "asc"
68+
69+
depends_on = [
70+
gitlab_project_tag.foo,
71+
]
72+
}
73+
`, testAccDataGitlabProjectTagsSetup(countTags, project), project)
74+
}
75+
76+
func testAccDataGitlabProjectTagsSetup(countTags int, project string) string {
77+
return fmt.Sprintf(`
78+
resource "gitlab_project_tag" "foo" {
79+
count = "%[1]d"
80+
81+
name = "${count.index}"
82+
ref = "main"
83+
project = "%s"
84+
message = "Tag ${count.index}"
85+
}
86+
`, countTags, project)
87+
}

0 commit comments

Comments
 (0)