diff --git a/digitalocean/datasource_digitalocean_tag.go b/digitalocean/datasource_digitalocean_tag.go index aa8f0486..b883d3c4 100644 --- a/digitalocean/datasource_digitalocean_tag.go +++ b/digitalocean/datasource_digitalocean_tag.go @@ -18,6 +18,30 @@ func dataSourceDigitalOceanTag() *schema.Resource { Description: "name of the tag", ValidateFunc: validateTag, }, + "total_resource_count": { + Type: schema.TypeInt, + Computed: true, + }, + "droplets_count": { + Type: schema.TypeInt, + Computed: true, + }, + "images_count": { + Type: schema.TypeInt, + Computed: true, + }, + "volumes_count": { + Type: schema.TypeInt, + Computed: true, + }, + "volume_snapshots_count": { + Type: schema.TypeInt, + Computed: true, + }, + "databases_count": { + Type: schema.TypeInt, + Computed: true, + }, }, } } @@ -37,6 +61,12 @@ func dataSourceDigitalOceanTagRead(d *schema.ResourceData, meta interface{}) err d.SetId(tag.Name) d.Set("name", tag.Name) + d.Set("total_resource_count", tag.Resources.Count) + d.Set("droplets_count", tag.Resources.Droplets.Count) + d.Set("images_count", tag.Resources.Images.Count) + d.Set("volumes_count", tag.Resources.Volumes.Count) + d.Set("volume_snapshots_count", tag.Resources.VolumeSnapshots.Count) + d.Set("databases_count", tag.Resources.Databases.Count) return nil } diff --git a/digitalocean/datasource_digitalocean_tag_test.go b/digitalocean/datasource_digitalocean_tag_test.go index 5de1b17d..f782fbee 100644 --- a/digitalocean/datasource_digitalocean_tag_test.go +++ b/digitalocean/datasource_digitalocean_tag_test.go @@ -25,6 +25,18 @@ func TestAccDataSourceDigitalOceanTag_Basic(t *testing.T) { testAccCheckDataSourceDigitalOceanTagExists("data.digitalocean_tag.foobar", &tag), resource.TestCheckResourceAttr( "data.digitalocean_tag.foobar", "name", tagName), + resource.TestCheckResourceAttrSet( + "data.digitalocean_tag.foobar", "total_resource_count"), + resource.TestCheckResourceAttrSet( + "data.digitalocean_tag.foobar", "droplets_count"), + resource.TestCheckResourceAttrSet( + "data.digitalocean_tag.foobar", "images_count"), + resource.TestCheckResourceAttrSet( + "data.digitalocean_tag.foobar", "volumes_count"), + resource.TestCheckResourceAttrSet( + "data.digitalocean_tag.foobar", "volume_snapshots_count"), + resource.TestCheckResourceAttrSet( + "data.digitalocean_tag.foobar", "databases_count"), ), }, }, diff --git a/digitalocean/datasource_digitalocean_tags.go b/digitalocean/datasource_digitalocean_tags.go new file mode 100644 index 00000000..955a937d --- /dev/null +++ b/digitalocean/datasource_digitalocean_tags.go @@ -0,0 +1,111 @@ +package digitalocean + +import ( + "context" + "fmt" + + "github.com/digitalocean/godo" + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + "github.com/terraform-providers/terraform-provider-digitalocean/internal/datalist" +) + +func dataSourceDigitalOceanTags() *schema.Resource { + dataListConfig := &datalist.ResourceConfig{ + RecordSchema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + }, + "total_resource_count": { + Type: schema.TypeInt, + }, + "droplets_count": { + Type: schema.TypeInt, + }, + "images_count": { + Type: schema.TypeInt, + }, + "volumes_count": { + Type: schema.TypeInt, + }, + "volume_snapshots_count": { + Type: schema.TypeInt, + }, + "databases_count": { + Type: schema.TypeInt, + }, + }, + FilterKeys: []string{ + "name", + "total_resource_count", + "droplets_count", + "images_count", + "volumes_count", + "volume_snapshots_count", + "databases_count", + }, + SortKeys: []string{ + "name", + "total_resource_count", + "droplets_count", + "images_count", + "volumes_count", + "volume_snapshots_count", + "databases_count", + }, + ResultAttributeName: "tags", + FlattenRecord: flattenDigitalOceanTag, + GetRecords: getDigitalOceanTags, + } + + return datalist.NewResource(dataListConfig) +} + +func getDigitalOceanTags(meta interface{}) ([]interface{}, error) { + client := meta.(*CombinedConfig).godoClient() + + tagsList := []interface{}{} + + opts := &godo.ListOptions{ + Page: 1, + PerPage: 200, + } + + for { + tags, resp, err := client.Tags.List(context.Background(), opts) + if err != nil { + return nil, fmt.Errorf("Error retrieving tags: %s", err) + } + + for _, tag := range tags { + tagsList = append(tagsList, tag) + } + + if resp.Links == nil || resp.Links.IsLastPage() { + break + } + + page, err := resp.Links.CurrentPage() + if err != nil { + return nil, fmt.Errorf("Error retrieving tags: %s", err) + } + + opts.Page = page + 1 + } + + return tagsList, nil +} + +func flattenDigitalOceanTag(tag, meta interface{}) (map[string]interface{}, error) { + t := tag.(godo.Tag) + + flattenedTag := map[string]interface{}{} + flattenedTag["name"] = t.Name + flattenedTag["total_resource_count"] = t.Resources.Count + flattenedTag["droplets_count"] = t.Resources.Droplets.Count + flattenedTag["images_count"] = t.Resources.Images.Count + flattenedTag["volumes_count"] = t.Resources.Volumes.Count + flattenedTag["volume_snapshots_count"] = t.Resources.VolumeSnapshots.Count + flattenedTag["databases_count"] = t.Resources.Databases.Count + + return flattenedTag, nil +} diff --git a/digitalocean/datasource_digitalocean_tags_test.go b/digitalocean/datasource_digitalocean_tags_test.go new file mode 100644 index 00000000..f8b37ef1 --- /dev/null +++ b/digitalocean/datasource_digitalocean_tags_test.go @@ -0,0 +1,55 @@ +package digitalocean + +import ( + "fmt" + "testing" + + "github.com/digitalocean/godo" + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" +) + +func TestAccDataSourceDigitalOceanTags_Basic(t *testing.T) { + var tag godo.Tag + tagName := randomTestName() + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: fmt.Sprintf(testAccCheckDataSourceDigitalOceanTagsConfig_basic, tagName), + Check: resource.ComposeTestCheckFunc( + testAccCheckDataSourceDigitalOceanTagExists("digitalocean_tag.foo", &tag), + resource.TestCheckResourceAttr( + "data.digitalocean_tags.foobar", "tags.0.name", tagName), + resource.TestCheckResourceAttrSet( + "data.digitalocean_tags.foobar", "tags.0.resource_count"), + resource.TestCheckResourceAttrSet( + "data.digitalocean_tag.foobar", "total_resource_count"), + resource.TestCheckResourceAttrSet( + "data.digitalocean_tag.foobar", "droplets_count"), + resource.TestCheckResourceAttrSet( + "data.digitalocean_tag.foobar", "images_count"), + resource.TestCheckResourceAttrSet( + "data.digitalocean_tag.foobar", "volumes_count"), + resource.TestCheckResourceAttrSet( + "data.digitalocean_tag.foobar", "volume_snapshots_count"), + resource.TestCheckResourceAttrSet( + "data.digitalocean_tag.foobar", "databases_count"), + ), + }, + }, + }) +} + +const testAccCheckDataSourceDigitalOceanTagsConfig_basic = ` +resource "digitalocean_tag" "foo" { + name = "%s" +} + +data "digitalocean_tags" "foobar" { + filter { + key = "name" + values = [digitalocean_tag.foo.name] + } +}` diff --git a/digitalocean/provider.go b/digitalocean/provider.go index bb6481bd..7f44419f 100644 --- a/digitalocean/provider.go +++ b/digitalocean/provider.go @@ -70,6 +70,7 @@ func Provider() terraform.ResourceProvider { "digitalocean_spaces_bucket_objects": dataSourceDigitalOceanSpacesBucketObjects(), "digitalocean_ssh_key": dataSourceDigitalOceanSSHKey(), "digitalocean_tag": dataSourceDigitalOceanTag(), + "digitalocean_tags": dataSourceDigitalOceanTags(), "digitalocean_volume_snapshot": dataSourceDigitalOceanVolumeSnapshot(), "digitalocean_volume": dataSourceDigitalOceanVolume(), "digitalocean_vpc": dataSourceDigitalOceanVPC(), diff --git a/digitalocean/resource_digitalocean_tag.go b/digitalocean/resource_digitalocean_tag.go index 8a502a39..1685501d 100644 --- a/digitalocean/resource_digitalocean_tag.go +++ b/digitalocean/resource_digitalocean_tag.go @@ -25,6 +25,30 @@ func resourceDigitalOceanTag() *schema.Resource { ForceNew: true, ValidateFunc: validateTag, }, + "total_resource_count": { + Type: schema.TypeInt, + Computed: true, + }, + "droplets_count": { + Type: schema.TypeInt, + Computed: true, + }, + "images_count": { + Type: schema.TypeInt, + Computed: true, + }, + "volumes_count": { + Type: schema.TypeInt, + Computed: true, + }, + "volume_snapshots_count": { + Type: schema.TypeInt, + Computed: true, + }, + "databases_count": { + Type: schema.TypeInt, + Computed: true, + }, }, } } @@ -65,6 +89,12 @@ func resourceDigitalOceanTagRead(d *schema.ResourceData, meta interface{}) error } d.Set("name", tag.Name) + d.Set("total_resource_count", tag.Resources.Count) + d.Set("droplets_count", tag.Resources.Droplets.Count) + d.Set("images_count", tag.Resources.Images.Count) + d.Set("volumes_count", tag.Resources.Volumes.Count) + d.Set("volume_snapshots_count", tag.Resources.VolumeSnapshots.Count) + d.Set("databases_count", tag.Resources.Databases.Count) return nil } diff --git a/digitalocean/resource_digitalocean_tag_test.go b/digitalocean/resource_digitalocean_tag_test.go index 556aae14..a8be3430 100644 --- a/digitalocean/resource_digitalocean_tag_test.go +++ b/digitalocean/resource_digitalocean_tag_test.go @@ -25,6 +25,18 @@ func TestAccDigitalOceanTag_Basic(t *testing.T) { testAccCheckDigitalOceanTagAttributes(&tag), resource.TestCheckResourceAttr( "digitalocean_tag.foobar", "name", "foobar"), + resource.TestCheckResourceAttrSet( + "digitalocean_tag.foobar", "total_resource_count"), + resource.TestCheckResourceAttrSet( + "digitalocean_tag.foobar", "droplets_count"), + resource.TestCheckResourceAttrSet( + "digitalocean_tag.foobar", "images_count"), + resource.TestCheckResourceAttrSet( + "digitalocean_tag.foobar", "volumes_count"), + resource.TestCheckResourceAttrSet( + "digitalocean_tag.foobar", "volume_snapshots_count"), + resource.TestCheckResourceAttrSet( + "digitalocean_tag.foobar", "databases_count"), ), }, }, diff --git a/website/digitalocean.erb b/website/digitalocean.erb index f4334994..c1b9315f 100644 --- a/website/digitalocean.erb +++ b/website/digitalocean.erb @@ -91,6 +91,9 @@ > digitalocean_tag + > + digitalocean_tags + > digitalocean_volume diff --git a/website/docs/d/sizes.html.md b/website/docs/d/sizes.html.md index fb4e2d5a..627a42e6 100644 --- a/website/docs/d/sizes.html.md +++ b/website/docs/d/sizes.html.md @@ -14,7 +14,7 @@ will be returned. ## Example Usage -Most common usage will probably be to supply a size to droplet: +Most common usage will probably be to supply a size to Droplet: ```hcl data "digitalocean_sizes" "main" { diff --git a/website/docs/d/tag.html.md b/website/docs/d/tag.html.md index 3540e73f..194a71c9 100644 --- a/website/docs/d/tag.html.md +++ b/website/docs/d/tag.html.md @@ -43,3 +43,9 @@ The following arguments are supported: The following attributes are exported: * `id`: The ID of the tag. +* `total_resource_count` - A count of the total number of resources that the tag is applied to. +* `droplets_count` - A count of the Droplets the tag is applied to. +* `images_count` - A count of the images that the tag is applied to. +* `volumes_count` - A count of the volumes that the tag is applied to. +* `volume_snapshots_count` - A count of the volume snapshots that the tag is applied to. +* `databases_count` - A count of the database clusters that the tag is applied to. diff --git a/website/docs/d/tags.html.md b/website/docs/d/tags.html.md new file mode 100644 index 00000000..ace55653 --- /dev/null +++ b/website/docs/d/tags.html.md @@ -0,0 +1,60 @@ +--- +layout: "digitalocean" +page_title: "DigitalOcean: digitalocean_tags" +sidebar_current: "docs-do-datasource-tags" +description: |- + Retrieve information on tags. +--- + +# digitalocean_tags + +Returns a list of tags in your DigitalOcean account, with the ability to +filter and sort the results. If no filters are specified, all tags will be +returned. + +## Example Usage + +```hcl +data "digitalocean_tags" "list" { + sort { + key = "total_resource_count" + direction = "asc" + } +} + +output "sorted_tags" { + value = data.digitalocean_tags.list.tags +} +``` + +## Argument Reference + +The following arguments are supported: + +* `filter` - (Optional) Filter the results. + The `filter` block is documented below. +* `sort` - (Optional) Sort the results. + The `sort` block is documented below. + +`filter` supports the following arguments: + +* `key` - (Required) Filter the tags by this key. This may be one of `name`, `total_resource_count`, `droplets_count`, `images_count`, `volumes_count`, `volume_snapshots_count`, or `databases_count`. +* `values` - (Required) Only retrieves tags which keys has value that matches + one of the values provided here. + +`sort` supports the following arguments: + +* `key` - (Required) Sort the tags by this key. This may be one of `name`, `total_resource_count`, `droplets_count`, `images_count`, `volumes_count`, `volume_snapshots_count`, or `databases_count`. +* `direction` - (Required) The sort direction. This may be either `asc` or `desc`. + +## Attributes Reference + +The following attributes are exported for each tag: + +* `name` - The name of the tag. +* `total_resource_count` - A count of the total number of resources that the tag is applied to. +* `droplets_count` - A count of the Droplets the tag is applied to. +* `images_count` - A count of the images that the tag is applied to. +* `volumes_count` - A count of the volumes that the tag is applied to. +* `volume_snapshots_count` - A count of the volume snapshots that the tag is applied to. +* `databases_count` - A count of the database clusters that the tag is applied to. diff --git a/website/docs/r/tag.html.markdown b/website/docs/r/tag.html.markdown index a57ab332..cda56fff 100644 --- a/website/docs/r/tag.html.markdown +++ b/website/docs/r/tag.html.markdown @@ -43,7 +43,12 @@ The following attributes are exported: * `id` - The id of the tag * `name` - The name of the tag - +* `total_resource_count` - A count of the total number of resources that the tag is applied to. +* `droplets_count` - A count of the Droplets the tag is applied to. +* `images_count` - A count of the images that the tag is applied to. +* `volumes_count` - A count of the volumes that the tag is applied to. +* `volume_snapshots_count` - A count of the volume snapshots that the tag is applied to. +* `databases_count` - A count of the database clusters that the tag is applied to. ## Import