Skip to content

Commit f6912dd

Browse files
pnodetjremy42
andauthored
feat(registry): add tag data source (#2696)
* feat(registry): add tag data source * fix(registry): remove invalid `Required` property from tag_data_source params * add doc and test * test: add func for push docker image in registry * test: fix test * test: fix lint * test: fix lint * modify doc --------- Co-authored-by: jremy <[email protected]>
1 parent 1909bce commit f6912dd

7 files changed

+2945
-0
lines changed
+58
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
---
2+
subcategory: "Container Registry"
3+
page_title: "Scaleway: scaleway_registry_image_tag"
4+
---
5+
6+
# scaleway_registry_image_tag
7+
8+
Gets information about a specific tag of a Container Registry image.
9+
10+
## Example Usage
11+
12+
```hcl
13+
# Get info by tag ID
14+
data "scaleway_registry_image_tag" "my_image_tag" {
15+
tag_id = "11111111-1111-1111-1111-111111111111"
16+
}
17+
18+
# Get info by name and image_id
19+
data "scaleway_registry_image_tag" "my_image_tag" {
20+
name = "my-tag-name"
21+
image_id = "22222222-2222-2222-2222-222222222222"
22+
}
23+
24+
```
25+
26+
## Argument Reference
27+
28+
- `tag_id` - The ID of the registry image tag.
29+
30+
- `image_id` - The ID of the registry image.
31+
32+
- `name` - The name of the registry image tag.
33+
34+
- `region` - (Defaults to provider region) The region in which the registry image tag exists.
35+
36+
- `organization_id` - (Defaults to provider organization_id) The ID of the organization the image tag is associated with.
37+
38+
- `project_id` - (Defaults to provider project_id) The ID of the project the image tag is associated with.
39+
40+
## Attributes Reference
41+
42+
In addition to all above arguments, the following attributes are exported:
43+
44+
- `id` - The ID of the registry image.
45+
46+
~> **Important:** Registry images' IDs are [regional](../guides/regions_and_zones.md#resource-ids), which means they are of the form `{region}/{id}`, e.g. `fr-par/11111111-1111-1111-1111-111111111111`
47+
48+
- `status` - The status of the registry image tag.
49+
50+
- `digest` - Hash of the tag content. Several tags of the same image may have the same digest.
51+
52+
- `created_at` - The date and time when the registry image tag was created.
53+
54+
- `updated_at` - The date and time of the last update to the registry image tag.
55+
56+
- `endpoint` - The endpoint where the registry image tag is accessible.
57+
58+
- `organization_id` - The organization ID the image tag is associated with.

internal/provider/provider.go

+1
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,7 @@ func Provider(config *Config) plugin.ProviderFunc {
299299
"scaleway_redis_cluster": redis.DataSourceCluster(),
300300
"scaleway_registry_image": registry.DataSourceImage(),
301301
"scaleway_registry_namespace": registry.DataSourceNamespace(),
302+
"scaleway_registry_image_tag": registry.DataSourceImageTag(),
302303
"scaleway_secret": secret.DataSourceSecret(),
303304
"scaleway_secret_version": secret.DataSourceVersion(),
304305
"scaleway_tem_domain": tem.DataSourceDomain(),
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
package registry
2+
3+
import (
4+
"context"
5+
6+
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
7+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
8+
"github.com/scaleway/scaleway-sdk-go/api/registry/v1"
9+
"github.com/scaleway/scaleway-sdk-go/scw"
10+
"github.com/scaleway/terraform-provider-scaleway/v2/internal/datasource"
11+
"github.com/scaleway/terraform-provider-scaleway/v2/internal/locality"
12+
"github.com/scaleway/terraform-provider-scaleway/v2/internal/locality/regional"
13+
"github.com/scaleway/terraform-provider-scaleway/v2/internal/services/account"
14+
"github.com/scaleway/terraform-provider-scaleway/v2/internal/types"
15+
"github.com/scaleway/terraform-provider-scaleway/v2/internal/verify"
16+
)
17+
18+
func DataSourceImageTag() *schema.Resource {
19+
return &schema.Resource{
20+
ReadContext: DataSourceImageTagRead,
21+
22+
Schema: map[string]*schema.Schema{
23+
"tag_id": {
24+
Type: schema.TypeString,
25+
Description: "The ID of the registry image tag",
26+
Optional: true,
27+
ConflictsWith: []string{"name"},
28+
ValidateDiagFunc: verify.IsUUIDorUUIDWithLocality(),
29+
},
30+
"image_id": {
31+
Type: schema.TypeString,
32+
Description: "The ID of the registry image",
33+
Required: true,
34+
ValidateDiagFunc: verify.IsUUIDorUUIDWithLocality(),
35+
},
36+
"name": {
37+
Type: schema.TypeString,
38+
Optional: true,
39+
Description: "The name of the registry image tag",
40+
ConflictsWith: []string{"tag_id"},
41+
},
42+
"status": {
43+
Type: schema.TypeString,
44+
Computed: true,
45+
Description: "The status of the registry image tag",
46+
},
47+
"digest": {
48+
Type: schema.TypeString,
49+
Computed: true,
50+
Description: "Hash of the tag content. Several tags of a same image may have the same digest",
51+
},
52+
"created_at": {
53+
Computed: true,
54+
Type: schema.TypeString,
55+
Description: "Date and time of creation",
56+
},
57+
"updated_at": {
58+
Computed: true,
59+
Type: schema.TypeString,
60+
Description: "Date and time of last update",
61+
},
62+
"region": regional.Schema(),
63+
"organization_id": account.OrganizationIDSchema(),
64+
"project_id": account.ProjectIDSchema(),
65+
},
66+
}
67+
}
68+
69+
func DataSourceImageTagRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
70+
api, region, err := NewAPIWithRegion(d, m)
71+
if err != nil {
72+
return diag.FromErr(err)
73+
}
74+
75+
var tag *registry.Tag
76+
tagID, tagIDExists := d.GetOk("tag_id")
77+
imageID := d.Get("image_id").(string)
78+
79+
if tagIDExists {
80+
res, err := api.GetTag(&registry.GetTagRequest{
81+
Region: region,
82+
TagID: locality.ExpandID(tagID),
83+
}, scw.WithContext(ctx))
84+
if err != nil {
85+
return diag.FromErr(err)
86+
}
87+
tag = res
88+
} else {
89+
tagName, nameExists := d.GetOk("name")
90+
if !nameExists {
91+
return diag.Errorf("either 'tag_id' or 'name' must be provided")
92+
}
93+
94+
res, err := api.ListTags(&registry.ListTagsRequest{
95+
Region: region,
96+
ImageID: locality.ExpandID(imageID),
97+
}, scw.WithContext(ctx))
98+
if err != nil {
99+
return diag.FromErr(err)
100+
}
101+
102+
foundTag, err := datasource.FindExact(res.Tags, func(s *registry.Tag) bool {
103+
return s.Name == tagName.(string)
104+
}, tagName.(string))
105+
if err != nil {
106+
return diag.FromErr(err)
107+
}
108+
109+
tag = foundTag
110+
}
111+
112+
d.SetId(datasource.NewRegionalID(tag.ID, region))
113+
_ = d.Set("tag_id", tag.ID)
114+
_ = d.Set("image_id", tag.ImageID)
115+
_ = d.Set("name", tag.Name)
116+
_ = d.Set("status", tag.Status.String())
117+
_ = d.Set("digest", tag.Digest)
118+
_ = d.Set("created_at", types.FlattenTime(tag.CreatedAt))
119+
_ = d.Set("updated_at", types.FlattenTime(tag.UpdatedAt))
120+
121+
return nil
122+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
package registry_test
2+
3+
import (
4+
"errors"
5+
"fmt"
6+
"testing"
7+
8+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
9+
"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
10+
registrySDK "github.com/scaleway/scaleway-sdk-go/api/registry/v1"
11+
"github.com/scaleway/terraform-provider-scaleway/v2/internal/acctest"
12+
"github.com/scaleway/terraform-provider-scaleway/v2/internal/locality"
13+
"github.com/scaleway/terraform-provider-scaleway/v2/internal/services/registry"
14+
registrytestfuncs "github.com/scaleway/terraform-provider-scaleway/v2/internal/services/registry/testfuncs"
15+
)
16+
17+
func TestAccDataSourceImageTag_Basic(t *testing.T) {
18+
tt := acctest.NewTestTools(t)
19+
defer tt.Cleanup()
20+
21+
expectedTagName := "test"
22+
namespaceName := "test-namespace-2"
23+
24+
resource.ParallelTest(t, resource.TestCase{
25+
PreCheck: func() { acctest.PreCheck(t) },
26+
ProviderFactories: tt.ProviderFactories,
27+
CheckDestroy: isNamespaceDestroyed(tt),
28+
Steps: []resource.TestStep{
29+
{
30+
Config: fmt.Sprintf(`
31+
resource "scaleway_registry_namespace" "test" {
32+
name = "%s"
33+
description = "Test namespace for Docker image"
34+
is_public = false
35+
}
36+
`, namespaceName),
37+
Check: resource.ComposeTestCheckFunc(
38+
func(s *terraform.State) error {
39+
rs, ok := s.RootModule().Resources["scaleway_registry_namespace.test"]
40+
if !ok {
41+
return errors.New("not found: scaleway_registry_namespace.test")
42+
}
43+
44+
endpoint := rs.Primary.Attributes["endpoint"]
45+
if endpoint == "" {
46+
return errors.New("no endpoint found for scaleway_registry_namespace.test")
47+
}
48+
49+
return registrytestfuncs.PushImageToRegistry(tt, endpoint, expectedTagName)(s)
50+
},
51+
),
52+
},
53+
{
54+
Config: fmt.Sprintf(`
55+
resource "scaleway_registry_namespace" "test" {
56+
name = "%s"
57+
description = "Test namespace for Docker image"
58+
is_public = false
59+
}
60+
61+
data "scaleway_registry_namespace" "test" {
62+
name = "%s"
63+
}
64+
65+
data "scaleway_registry_image" "image" {
66+
name = "alpine"
67+
}
68+
69+
data "scaleway_registry_image_tag" "tag" {
70+
name = "%s"
71+
image_id = "${data.scaleway_registry_image.image.id}"
72+
}
73+
`, namespaceName, namespaceName, expectedTagName),
74+
Check: resource.ComposeTestCheckFunc(
75+
isTagPresent(tt, "data.scaleway_registry_image_tag.tag"),
76+
isNamespacePresent(tt, "scaleway_registry_namespace.test"),
77+
resource.TestCheckResourceAttr("data.scaleway_registry_image_tag.tag", "name", expectedTagName),
78+
resource.TestCheckResourceAttrSet("data.scaleway_registry_image_tag.tag", "digest"),
79+
resource.TestCheckResourceAttrSet("data.scaleway_registry_image_tag.tag", "created_at"),
80+
resource.TestCheckResourceAttrSet("data.scaleway_registry_image_tag.tag", "updated_at"),
81+
),
82+
},
83+
{
84+
Config: fmt.Sprintf(`
85+
resource "scaleway_registry_namespace" "test" {
86+
name = "%s"
87+
description = "Test namespace for Docker image"
88+
is_public = false
89+
}
90+
91+
data "scaleway_registry_namespace" "test" {
92+
name = "%s"
93+
}
94+
95+
data "scaleway_registry_image" "image" {
96+
name = "alpine"
97+
}
98+
`, namespaceName, namespaceName),
99+
Check: resource.ComposeTestCheckFunc(
100+
deleteImage(tt, "data.scaleway_registry_image.image"),
101+
),
102+
},
103+
},
104+
})
105+
}
106+
107+
func isTagPresent(tt *acctest.TestTools, n string) resource.TestCheckFunc {
108+
return func(state *terraform.State) error {
109+
rs, ok := state.RootModule().Resources[n]
110+
if !ok {
111+
return fmt.Errorf("resource not found: %s", n)
112+
}
113+
114+
api, region, _, err := registry.NewAPIWithRegionAndID(tt.Meta, rs.Primary.ID)
115+
if err != nil {
116+
return err
117+
}
118+
119+
_, err = api.GetTag(&registrySDK.GetTagRequest{
120+
TagID: locality.ExpandID(rs.Primary.ID),
121+
Region: region,
122+
})
123+
if err != nil {
124+
return err
125+
}
126+
127+
return nil
128+
}
129+
}
130+
131+
func deleteImage(tt *acctest.TestTools, n string) resource.TestCheckFunc {
132+
return func(state *terraform.State) error {
133+
rs, ok := state.RootModule().Resources[n]
134+
if !ok {
135+
return fmt.Errorf("resource not found: %s", n)
136+
}
137+
api, region, _, err := registry.NewAPIWithRegionAndID(tt.Meta, rs.Primary.ID)
138+
if err != nil {
139+
return err
140+
}
141+
_, err = api.DeleteImage(&registrySDK.DeleteImageRequest{
142+
Region: region,
143+
ImageID: locality.ExpandID(rs.Primary.ID),
144+
})
145+
if err != nil {
146+
return err
147+
}
148+
149+
return nil
150+
}
151+
}

0 commit comments

Comments
 (0)