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 @@