add digitalocean_droplets data source (#418)
* add digitalocean_droplets data source * add docs * Update website/docs/d/droplets.html.md Co-Authored-By: Andrew Starr-Bochicchio <andrewsomething@users.noreply.github.com> * Update website/docs/d/droplets.html.md Co-Authored-By: Andrew Starr-Bochicchio <andrewsomething@users.noreply.github.com> * Update digitalocean/droplets.go Co-Authored-By: Andrew Starr-Bochicchio <andrewsomething@users.noreply.github.com> * Import strconv Co-authored-by: Andrew Starr-Bochicchio <andrewsomething@users.noreply.github.com> Co-authored-by: Andrew Starr-Bochicchio <a.starr.b@gmail.com>
This commit is contained in:
parent
0fea588f83
commit
11fd5a433a
|
@ -4,7 +4,6 @@ import (
|
|||
"context"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/digitalocean/godo"
|
||||
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
|
||||
|
@ -12,217 +11,91 @@ import (
|
|||
)
|
||||
|
||||
func dataSourceDigitalOceanDroplet() *schema.Resource {
|
||||
recordSchema := dropletSchema()
|
||||
|
||||
for _, f := range recordSchema {
|
||||
f.Computed = true
|
||||
}
|
||||
|
||||
recordSchema["id"].ExactlyOneOf = []string{"id", "tag", "name"}
|
||||
recordSchema["id"].Optional = true
|
||||
recordSchema["name"].ExactlyOneOf = []string{"id", "tag", "name"}
|
||||
recordSchema["name"].Optional = true
|
||||
|
||||
recordSchema["tag"] = &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
Description: "unique tag of the Droplet",
|
||||
ValidateFunc: validation.NoZeroValues,
|
||||
ExactlyOneOf: []string{"id", "tag", "name"},
|
||||
}
|
||||
|
||||
return &schema.Resource{
|
||||
Read: dataSourceDigitalOceanDropletRead,
|
||||
Schema: map[string]*schema.Schema{
|
||||
"id": {
|
||||
Type: schema.TypeInt,
|
||||
Optional: true,
|
||||
Description: "id of the Droplet",
|
||||
ValidateFunc: validation.NoZeroValues,
|
||||
ExactlyOneOf: []string{"id", "tag", "name"},
|
||||
},
|
||||
"tag": {
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
Description: "unique tag of the Droplet",
|
||||
ValidateFunc: validation.NoZeroValues,
|
||||
ExactlyOneOf: []string{"id", "tag", "name"},
|
||||
},
|
||||
"name": {
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
Description: "name of the Droplet",
|
||||
ValidateFunc: validation.NoZeroValues,
|
||||
ExactlyOneOf: []string{"id", "tag", "name"},
|
||||
},
|
||||
// computed attributes
|
||||
"created_at": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
Description: "the creation date for the Droplet",
|
||||
},
|
||||
"urn": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
Description: "the uniform resource name for the Droplet",
|
||||
},
|
||||
"region": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
Description: "the region that the Droplet instance is deployed in",
|
||||
},
|
||||
"image": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
Description: "the image id or slug of the Droplet",
|
||||
},
|
||||
"size": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
Description: "the current size of the Droplet",
|
||||
},
|
||||
"disk": {
|
||||
Type: schema.TypeInt,
|
||||
Computed: true,
|
||||
Description: "the size of the Droplets disk in gigabytes",
|
||||
},
|
||||
"vcpus": {
|
||||
Type: schema.TypeInt,
|
||||
Computed: true,
|
||||
Description: "the number of virtual cpus",
|
||||
},
|
||||
"memory": {
|
||||
Type: schema.TypeInt,
|
||||
Computed: true,
|
||||
Description: "memory of the Droplet in megabytes",
|
||||
},
|
||||
"price_hourly": {
|
||||
Type: schema.TypeFloat,
|
||||
Computed: true,
|
||||
Description: "the Droplets hourly price",
|
||||
},
|
||||
"price_monthly": {
|
||||
Type: schema.TypeFloat,
|
||||
Computed: true,
|
||||
Description: "the Droplets monthly price",
|
||||
},
|
||||
"status": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
Description: "state of the Droplet instance",
|
||||
},
|
||||
"locked": {
|
||||
Type: schema.TypeBool,
|
||||
Computed: true,
|
||||
Description: "whether the Droplet has been locked",
|
||||
},
|
||||
"ipv4_address": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
Description: "the Droplets public ipv4 address",
|
||||
},
|
||||
"ipv4_address_private": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
Description: "the Droplets private ipv4 address",
|
||||
},
|
||||
"ipv6_address": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
Description: "the Droplets public ipv6 address",
|
||||
},
|
||||
"ipv6_address_private": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
Description: "the Droplets private ipv4 address",
|
||||
},
|
||||
"backups": {
|
||||
Type: schema.TypeBool,
|
||||
Computed: true,
|
||||
Description: "whether the Droplet has backups enabled",
|
||||
},
|
||||
"ipv6": {
|
||||
Type: schema.TypeBool,
|
||||
Computed: true,
|
||||
Description: "whether the Droplet has ipv6 enabled",
|
||||
},
|
||||
"private_networking": {
|
||||
Type: schema.TypeBool,
|
||||
Computed: true,
|
||||
Description: "whether the Droplet has private networking enabled",
|
||||
},
|
||||
"monitoring": {
|
||||
Type: schema.TypeBool,
|
||||
Computed: true,
|
||||
Description: "whether the Droplet has monitoring enabled",
|
||||
},
|
||||
"volume_ids": {
|
||||
Type: schema.TypeSet,
|
||||
Elem: &schema.Schema{Type: schema.TypeString},
|
||||
Computed: true,
|
||||
Description: "list of volumes attached to the Droplet",
|
||||
},
|
||||
"tags": tagsDataSourceSchema(),
|
||||
"vpc_uuid": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
Description: "UUID of the VPC in which the Droplet is located",
|
||||
},
|
||||
},
|
||||
Read: dataSourceDigitalOceanDropletRead,
|
||||
Schema: recordSchema,
|
||||
}
|
||||
}
|
||||
|
||||
func dataSourceDigitalOceanDropletRead(d *schema.ResourceData, meta interface{}) error {
|
||||
client := meta.(*CombinedConfig).godoClient()
|
||||
|
||||
var foundDroplet godo.Droplet
|
||||
|
||||
if id, ok := d.GetOk("id"); ok {
|
||||
droplet, _, err := client.Droplets.Get(context.Background(), id.(int))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
exportDropletProperties(d, droplet)
|
||||
return nil
|
||||
}
|
||||
|
||||
opts := &godo.ListOptions{
|
||||
Page: 1,
|
||||
PerPage: 200,
|
||||
}
|
||||
|
||||
dropletList := []godo.Droplet{}
|
||||
|
||||
for {
|
||||
droplets, resp, err := client.Droplets.List(context.Background(), opts)
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error retrieving droplets: %s", err)
|
||||
}
|
||||
|
||||
for _, droplet := range droplets {
|
||||
dropletList = append(dropletList, droplet)
|
||||
}
|
||||
|
||||
if resp.Links == nil || resp.Links.IsLastPage() {
|
||||
break
|
||||
}
|
||||
|
||||
page, err := resp.Links.CurrentPage()
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error retrieving droplets: %s", err)
|
||||
}
|
||||
|
||||
opts.Page = page + 1
|
||||
}
|
||||
|
||||
if v, ok := d.GetOk("tag"); ok {
|
||||
droplet, err := findDropletByTag(dropletList, v.(string))
|
||||
|
||||
foundDroplet = *droplet
|
||||
} else if v, ok := d.GetOk("tag"); ok {
|
||||
dropletList, err := getDigitalOceanDroplets(meta)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
exportDropletProperties(d, droplet)
|
||||
droplet, err := findDropletByTag(dropletList, v.(string))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
foundDroplet = *droplet
|
||||
} else if v, ok := d.GetOk("name"); ok {
|
||||
dropletList, err := getDigitalOceanDroplets(meta)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
droplet, err := findDropletByName(dropletList, v.(string))
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
exportDropletProperties(d, droplet)
|
||||
foundDroplet = *droplet
|
||||
} else {
|
||||
return fmt.Errorf("Error: specify either a name, tag, or id to use to look up the droplet")
|
||||
}
|
||||
|
||||
flattenedDroplet, err := flattenDigitalOceanDroplet(foundDroplet, meta)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := setResourceDataFromMap(d, flattenedDroplet); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
d.SetId(strconv.Itoa(foundDroplet.ID))
|
||||
return nil
|
||||
}
|
||||
|
||||
func findDropletByName(droplets []godo.Droplet, name string) (*godo.Droplet, error) {
|
||||
func findDropletByName(droplets []interface{}, name string) (*godo.Droplet, error) {
|
||||
results := make([]godo.Droplet, 0)
|
||||
for _, v := range droplets {
|
||||
if v.Name == name {
|
||||
results = append(results, v)
|
||||
droplet := v.(godo.Droplet)
|
||||
if droplet.Name == name {
|
||||
results = append(results, droplet)
|
||||
}
|
||||
}
|
||||
if len(results) == 1 {
|
||||
|
@ -234,12 +107,13 @@ func findDropletByName(droplets []godo.Droplet, name string) (*godo.Droplet, err
|
|||
return nil, fmt.Errorf("too many droplets found with name %s (found %d, expected 1)", name, len(results))
|
||||
}
|
||||
|
||||
func findDropletByTag(droplets []godo.Droplet, tag string) (*godo.Droplet, error) {
|
||||
func findDropletByTag(droplets []interface{}, tag string) (*godo.Droplet, error) {
|
||||
results := make([]godo.Droplet, 0)
|
||||
for _, d := range droplets {
|
||||
for _, t := range d.Tags {
|
||||
droplet := d.(godo.Droplet)
|
||||
for _, t := range droplet.Tags {
|
||||
if t == tag {
|
||||
results = append(results, d)
|
||||
results = append(results, droplet)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -251,59 +125,3 @@ func findDropletByTag(droplets []godo.Droplet, tag string) (*godo.Droplet, error
|
|||
}
|
||||
return nil, fmt.Errorf("too many droplets found with tag %s (found %d, expected 1)", tag, len(results))
|
||||
}
|
||||
|
||||
func exportDropletProperties(d *schema.ResourceData, droplet *godo.Droplet) error {
|
||||
d.SetId(strconv.Itoa(droplet.ID))
|
||||
d.Set("name", droplet.Name)
|
||||
d.Set("urn", droplet.URN())
|
||||
d.Set("region", droplet.Region.Slug)
|
||||
d.Set("size", droplet.Size.Slug)
|
||||
d.Set("price_hourly", droplet.Size.PriceHourly)
|
||||
d.Set("price_monthly", droplet.Size.PriceMonthly)
|
||||
d.Set("disk", droplet.Disk)
|
||||
d.Set("vcpus", droplet.Vcpus)
|
||||
d.Set("memory", droplet.Memory)
|
||||
d.Set("status", droplet.Status)
|
||||
d.Set("locked", droplet.Locked)
|
||||
d.Set("created_at", droplet.Created)
|
||||
d.Set("vpc_uuid", droplet.VPCUUID)
|
||||
|
||||
if droplet.Image.Slug == "" {
|
||||
d.Set("image", droplet.Image.ID)
|
||||
} else {
|
||||
d.Set("image", droplet.Image.Slug)
|
||||
}
|
||||
|
||||
if publicIPv4 := findIPv4AddrByType(droplet, "public"); publicIPv4 != "" {
|
||||
d.Set("ipv4_address", publicIPv4)
|
||||
}
|
||||
|
||||
if privateIPv4 := findIPv4AddrByType(droplet, "private"); privateIPv4 != "" {
|
||||
d.Set("ipv4_address_private", privateIPv4)
|
||||
}
|
||||
|
||||
if publicIPv6 := findIPv6AddrByType(droplet, "public"); publicIPv6 != "" {
|
||||
d.Set("ipv6_address", strings.ToLower(publicIPv6))
|
||||
}
|
||||
|
||||
if privateIPv6 := findIPv6AddrByType(droplet, "private"); privateIPv6 != "" {
|
||||
d.Set("ipv6_address_private", strings.ToLower(privateIPv6))
|
||||
}
|
||||
|
||||
if features := droplet.Features; features != nil {
|
||||
d.Set("backups", containsDigitalOceanDropletFeature(features, "backups"))
|
||||
d.Set("ipv6", containsDigitalOceanDropletFeature(features, "ipv6"))
|
||||
d.Set("private_networking", containsDigitalOceanDropletFeature(features, "private_networking"))
|
||||
d.Set("monitoring", containsDigitalOceanDropletFeature(features, "monitoring"))
|
||||
}
|
||||
|
||||
if err := d.Set("volume_ids", flattenDigitalOceanDropletVolumeIds(droplet.VolumeIDs)); err != nil {
|
||||
return fmt.Errorf("Error setting `volume_ids`: %+v", err)
|
||||
}
|
||||
|
||||
if err := d.Set("tags", flattenTags(droplet.Tags)); err != nil {
|
||||
return fmt.Errorf("Error setting `tags`: %+v", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -0,0 +1,69 @@
|
|||
package digitalocean
|
||||
|
||||
import (
|
||||
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
|
||||
"github.com/terraform-providers/terraform-provider-digitalocean/internal/datalist"
|
||||
)
|
||||
|
||||
func dataSourceDigitalOceanDroplets() *schema.Resource {
|
||||
dataListConfig := &datalist.ResourceConfig{
|
||||
RecordSchema: dropletSchema(),
|
||||
FilterKeys: []string{
|
||||
"id",
|
||||
"name",
|
||||
"created_at",
|
||||
"urn",
|
||||
"region",
|
||||
"image",
|
||||
"size",
|
||||
"disk",
|
||||
"vcpus",
|
||||
"memory",
|
||||
"price_hourly",
|
||||
"price_monthly",
|
||||
"status",
|
||||
"locked",
|
||||
"ipv4_address",
|
||||
"ipv4_address_private",
|
||||
"ipv6_address",
|
||||
"ipv6_address_private",
|
||||
"backups",
|
||||
"ipv6",
|
||||
"private_networking",
|
||||
"monitoring",
|
||||
"volume_ids",
|
||||
"tags",
|
||||
"vpc_uuid",
|
||||
},
|
||||
SortKeys: []string{
|
||||
"id",
|
||||
"name",
|
||||
"created_at",
|
||||
"urn",
|
||||
"region",
|
||||
"image",
|
||||
"size",
|
||||
"disk",
|
||||
"vcpus",
|
||||
"memory",
|
||||
"price_hourly",
|
||||
"price_monthly",
|
||||
"status",
|
||||
"locked",
|
||||
"ipv4_address",
|
||||
"ipv4_address_private",
|
||||
"ipv6_address",
|
||||
"ipv6_address_private",
|
||||
"backups",
|
||||
"ipv6",
|
||||
"private_networking",
|
||||
"monitoring",
|
||||
"vpc_uuid",
|
||||
},
|
||||
ResultAttributeName: "droplets",
|
||||
GetRecords: getDigitalOceanDroplets,
|
||||
FlattenRecord: flattenDigitalOceanDroplet,
|
||||
}
|
||||
|
||||
return datalist.NewResource(dataListConfig)
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
package digitalocean
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/terraform-plugin-sdk/helper/acctest"
|
||||
"github.com/hashicorp/terraform-plugin-sdk/helper/resource"
|
||||
)
|
||||
|
||||
func TestAccDataSourceDigitalOceanDroplets_Basic(t *testing.T) {
|
||||
name1 := fmt.Sprintf("tf-acc-test-%s", acctest.RandString(10))
|
||||
name2 := fmt.Sprintf("tf-acc-test-%s", acctest.RandString(10))
|
||||
|
||||
resourcesConfig := fmt.Sprintf(`
|
||||
resource "digitalocean_droplet" "foo" {
|
||||
name = "%s"
|
||||
size = "s-1vcpu-1gb"
|
||||
image = "centos-7-x64"
|
||||
region = "nyc3"
|
||||
}
|
||||
|
||||
resource "digitalocean_droplet" "bar" {
|
||||
name = "%s"
|
||||
size = "s-1vcpu-1gb"
|
||||
image = "centos-7-x64"
|
||||
region = "nyc3"
|
||||
}
|
||||
`, name1, name2)
|
||||
|
||||
datasourceConfig := fmt.Sprintf(`
|
||||
data "digitalocean_droplets" "result" {
|
||||
filter {
|
||||
key = "name"
|
||||
values = ["%s"]
|
||||
}
|
||||
}
|
||||
`, name1)
|
||||
resource.Test(t, resource.TestCase{
|
||||
PreCheck: func() { testAccPreCheck(t) },
|
||||
Providers: testAccProviders,
|
||||
Steps: []resource.TestStep{
|
||||
{
|
||||
Config: resourcesConfig,
|
||||
},
|
||||
{
|
||||
Config: resourcesConfig + datasourceConfig,
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
resource.TestCheckResourceAttr("data.digitalocean_droplets.result", "droplets.#", "1"),
|
||||
resource.TestCheckResourceAttr("data.digitalocean_droplets.result", "droplets.0.name", name1),
|
||||
),
|
||||
},
|
||||
{
|
||||
Config: resourcesConfig,
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
|
@ -0,0 +1,205 @@
|
|||
package digitalocean
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/digitalocean/godo"
|
||||
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
|
||||
)
|
||||
|
||||
func dropletSchema() map[string]*schema.Schema {
|
||||
return map[string]*schema.Schema{
|
||||
"id": {
|
||||
Type: schema.TypeInt,
|
||||
Description: "id of the Droplet",
|
||||
},
|
||||
"name": {
|
||||
Type: schema.TypeString,
|
||||
Description: "name of the Droplet",
|
||||
},
|
||||
"created_at": {
|
||||
Type: schema.TypeString,
|
||||
Description: "the creation date for the Droplet",
|
||||
},
|
||||
"urn": {
|
||||
Type: schema.TypeString,
|
||||
Description: "the uniform resource name for the Droplet",
|
||||
},
|
||||
"region": {
|
||||
Type: schema.TypeString,
|
||||
Description: "the region that the Droplet instance is deployed in",
|
||||
},
|
||||
"image": {
|
||||
Type: schema.TypeString,
|
||||
Description: "the image id or slug of the Droplet",
|
||||
},
|
||||
"size": {
|
||||
Type: schema.TypeString,
|
||||
Description: "the current size of the Droplet",
|
||||
},
|
||||
"disk": {
|
||||
Type: schema.TypeInt,
|
||||
Description: "the size of the Droplets disk in gigabytes",
|
||||
},
|
||||
"vcpus": {
|
||||
Type: schema.TypeInt,
|
||||
Description: "the number of virtual cpus",
|
||||
},
|
||||
"memory": {
|
||||
Type: schema.TypeInt,
|
||||
Description: "memory of the Droplet in megabytes",
|
||||
},
|
||||
"price_hourly": {
|
||||
Type: schema.TypeFloat,
|
||||
Description: "the Droplets hourly price",
|
||||
},
|
||||
"price_monthly": {
|
||||
Type: schema.TypeFloat,
|
||||
Description: "the Droplets monthly price",
|
||||
},
|
||||
"status": {
|
||||
Type: schema.TypeString,
|
||||
Description: "state of the Droplet instance",
|
||||
},
|
||||
"locked": {
|
||||
Type: schema.TypeBool,
|
||||
Description: "whether the Droplet has been locked",
|
||||
},
|
||||
"ipv4_address": {
|
||||
Type: schema.TypeString,
|
||||
Description: "the Droplets public ipv4 address",
|
||||
},
|
||||
"ipv4_address_private": {
|
||||
Type: schema.TypeString,
|
||||
Description: "the Droplets private ipv4 address",
|
||||
},
|
||||
"ipv6_address": {
|
||||
Type: schema.TypeString,
|
||||
Description: "the Droplets public ipv6 address",
|
||||
},
|
||||
"ipv6_address_private": {
|
||||
Type: schema.TypeString,
|
||||
Description: "the Droplets private ipv4 address",
|
||||
},
|
||||
"backups": {
|
||||
Type: schema.TypeBool,
|
||||
Description: "whether the Droplet has backups enabled",
|
||||
},
|
||||
"ipv6": {
|
||||
Type: schema.TypeBool,
|
||||
Description: "whether the Droplet has ipv6 enabled",
|
||||
},
|
||||
"private_networking": {
|
||||
Type: schema.TypeBool,
|
||||
Description: "whether the Droplet has private networking enabled",
|
||||
},
|
||||
"monitoring": {
|
||||
Type: schema.TypeBool,
|
||||
Description: "whether the Droplet has monitoring enabled",
|
||||
},
|
||||
"volume_ids": {
|
||||
Type: schema.TypeSet,
|
||||
Elem: &schema.Schema{Type: schema.TypeString},
|
||||
Description: "list of volumes attached to the Droplet",
|
||||
},
|
||||
"tags": tagsDataSourceSchema(),
|
||||
"vpc_uuid": {
|
||||
Type: schema.TypeString,
|
||||
Description: "UUID of the VPC in which the Droplet is located",
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func getDigitalOceanDroplets(meta interface{}) ([]interface{}, error) {
|
||||
client := meta.(*CombinedConfig).godoClient()
|
||||
|
||||
opts := &godo.ListOptions{
|
||||
Page: 1,
|
||||
PerPage: 200,
|
||||
}
|
||||
|
||||
var dropletList []interface{}
|
||||
|
||||
for {
|
||||
droplets, resp, err := client.Droplets.List(context.Background(), opts)
|
||||
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Error retrieving droplets: %s", err)
|
||||
}
|
||||
|
||||
for _, droplet := range droplets {
|
||||
dropletList = append(dropletList, droplet)
|
||||
}
|
||||
|
||||
if resp.Links == nil || resp.Links.IsLastPage() {
|
||||
break
|
||||
}
|
||||
|
||||
page, err := resp.Links.CurrentPage()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Error retrieving droplets: %s", err)
|
||||
}
|
||||
|
||||
opts.Page = page + 1
|
||||
}
|
||||
|
||||
return dropletList, nil
|
||||
}
|
||||
|
||||
func flattenDigitalOceanDroplet(rawDroplet, meta interface{}) (map[string]interface{}, error) {
|
||||
droplet := rawDroplet.(godo.Droplet)
|
||||
|
||||
flattenedDroplet := map[string]interface{}{
|
||||
"name": droplet.Name,
|
||||
"urn": droplet.URN(),
|
||||
"region": droplet.Region.Slug,
|
||||
"size": droplet.Size.Slug,
|
||||
"price_hourly": droplet.Size.PriceHourly,
|
||||
"price_monthly": droplet.Size.PriceMonthly,
|
||||
"disk": droplet.Disk,
|
||||
"vcpus": droplet.Vcpus,
|
||||
"memory": droplet.Memory,
|
||||
"status": droplet.Status,
|
||||
"locked": droplet.Locked,
|
||||
"created_at": droplet.Created,
|
||||
"vpc_uuid": droplet.VPCUUID,
|
||||
}
|
||||
|
||||
if droplet.Image.Slug == "" {
|
||||
flattenedDroplet["image"] = strconv.Itoa(droplet.Image.ID)
|
||||
} else {
|
||||
flattenedDroplet["image"] = droplet.Image.Slug
|
||||
}
|
||||
|
||||
if publicIPv4 := findIPv4AddrByType(&droplet, "public"); publicIPv4 != "" {
|
||||
flattenedDroplet["ipv4_address"] = publicIPv4
|
||||
}
|
||||
|
||||
if privateIPv4 := findIPv4AddrByType(&droplet, "private"); privateIPv4 != "" {
|
||||
flattenedDroplet["ipv4_address_private"] = privateIPv4
|
||||
}
|
||||
|
||||
if publicIPv6 := findIPv6AddrByType(&droplet, "public"); publicIPv6 != "" {
|
||||
flattenedDroplet["ipv6_address"] = strings.ToLower(publicIPv6)
|
||||
}
|
||||
|
||||
if privateIPv6 := findIPv6AddrByType(&droplet, "private"); privateIPv6 != "" {
|
||||
flattenedDroplet["ipv6_address_private"] = strings.ToLower(privateIPv6)
|
||||
}
|
||||
|
||||
if features := droplet.Features; features != nil {
|
||||
flattenedDroplet["backups"] = containsDigitalOceanDropletFeature(features, "backups")
|
||||
flattenedDroplet["ipv6"] = containsDigitalOceanDropletFeature(features, "ipv6")
|
||||
flattenedDroplet["private_networking"] = containsDigitalOceanDropletFeature(features, "private_networking")
|
||||
flattenedDroplet["monitoring"] = containsDigitalOceanDropletFeature(features, "monitoring")
|
||||
}
|
||||
|
||||
flattenedDroplet["volume_ids"] = flattenDigitalOceanDropletVolumeIds(droplet.VolumeIDs)
|
||||
|
||||
flattenedDroplet["tags"] = flattenTags(droplet.Tags)
|
||||
|
||||
return flattenedDroplet, nil
|
||||
}
|
|
@ -50,6 +50,7 @@ func Provider() terraform.ResourceProvider {
|
|||
"digitalocean_database_cluster": dataSourceDigitalOceanDatabaseCluster(),
|
||||
"digitalocean_domain": dataSourceDigitalOceanDomain(),
|
||||
"digitalocean_droplet": dataSourceDigitalOceanDroplet(),
|
||||
"digitalocean_droplets": dataSourceDigitalOceanDroplets(),
|
||||
"digitalocean_droplet_snapshot": dataSourceDigitalOceanDropletSnapshot(),
|
||||
"digitalocean_floating_ip": dataSourceDigitalOceanFloatingIp(),
|
||||
"digitalocean_image": dataSourceDigitalOceanImage(),
|
||||
|
|
|
@ -111,6 +111,11 @@ func dataListResourceRead(config *ResourceConfig) schema.ReadFunc {
|
|||
|
||||
// Validate a ResourceConfig to ensure it conforms to this package's assumptions.
|
||||
func validateResourceConfig(config *ResourceConfig) error {
|
||||
// Ensure that ResultAttributeName exists.
|
||||
if config.ResultAttributeName == "" {
|
||||
return fmt.Errorf("ResultAttributeName must be specified")
|
||||
}
|
||||
|
||||
// Ensure that all of the filter keys exist in the schema and are of a supported type.
|
||||
for _, filterKey := range config.FilterKeys {
|
||||
if s, ok := config.RecordSchema[filterKey]; ok {
|
||||
|
|
|
@ -28,6 +28,9 @@
|
|||
<li<%= sidebar_current("docs-do-datasource-droplet") %>>
|
||||
<a href="/docs/providers/do/d/droplet.html">digitalocean_droplet</a>
|
||||
</li>
|
||||
<li<%= sidebar_current("docs-do-datasource-droplets") %>>
|
||||
<a href="/docs/providers/do/d/droplets.html">digitalocean_droplets</a>
|
||||
</li>
|
||||
<li<%= sidebar_current("docs-do-datasource-droplet-snapshot") %>>
|
||||
<a href="/docs/providers/do/d/droplet_snapshot.html">digitalocean_droplet_snapshot</a>
|
||||
</li>
|
||||
|
|
|
@ -0,0 +1,107 @@
|
|||
---
|
||||
layout: "digitalocean"
|
||||
page_title: "DigitalOcean: digitalocean_droplets"
|
||||
sidebar_current: "docs-do-datasource-droplets"
|
||||
description: |-
|
||||
Retrieve information on Droplets.
|
||||
---
|
||||
|
||||
# digitalocean_droplets
|
||||
|
||||
Get information on Droplets for use in other resources, with the ability to filter and sort the results.
|
||||
If no filters are specified, all Droplets will be returned.
|
||||
|
||||
This data source is useful if the Droplets in question are not managed by Terraform or you need to
|
||||
utilize any of the Droplets' data.
|
||||
|
||||
Note: You can use the [`digitalocean_droplet`](/docs/providers/do/d/droplet.html) data source to obtain metadata
|
||||
about a single Droplet if you already know the `id`, unique `name`, or unique `tag` to retrieve.
|
||||
|
||||
## Example Usage
|
||||
|
||||
Use the `filter` block with a `key` string and `values` list to filter images.
|
||||
|
||||
For example to find all Droplets with size `s-1vcpu-1gb`:
|
||||
|
||||
```hcl
|
||||
data "digitalocean_droplets" "small" {
|
||||
filter {
|
||||
key = "size"
|
||||
values = ["s-1vcpu-1gb"]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
You can filter on multiple fields and sort the results as well:
|
||||
|
||||
```hcl
|
||||
data "digitalocean_droplets" "small-with-backups" {
|
||||
filter {
|
||||
key = "size"
|
||||
values = ["s-1vcpu-1gb"]
|
||||
}
|
||||
filter {
|
||||
key = "backups"
|
||||
values = ["true"]
|
||||
}
|
||||
sort {
|
||||
key = "created_at"
|
||||
direction = "desc"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Argument Reference
|
||||
|
||||
* `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 Droplets by this key. This may be one of '`backups`, `created_at`, `disk`, `id`,
|
||||
`image`, `ipv4_address`, `ipv4_address_private`, `ipv6`, `ipv6_address`, `ipv6_address_private`, `locked`,
|
||||
`memory`, `monitoring`, `name`, `price_hourly`, `price_monthly`, `private_networking`, `region`, `size`,
|
||||
`status`, `tags`, `urn`, `vcpus`, `volume_ids`, or `vpc_uuid`'.
|
||||
|
||||
* `values` - (Required) A list of values to match against the `key` field. Only retrieves Droplets
|
||||
where the `key` field takes on one or more of the values provided here.
|
||||
|
||||
`sort` supports the following arguments:
|
||||
|
||||
* `key` - (Required) Sort the Droplets by this key. This may be one of `backups`, `created_at`, `disk`, `id`,
|
||||
`image`, `ipv4_address`, `ipv4_address_private`, `ipv6`, `ipv6_address`, `ipv6_address_private`, `locked`,
|
||||
`memory`, `monitoring`, `name`, `price_hourly`, `price_monthly`, `private_networking`, `region`, `size`,
|
||||
`status`, `urn`, `vcpus`, or `vpc_uuid`.
|
||||
|
||||
* `direction` - (Required) The sort direction. This may be either `asc` or `desc`.
|
||||
|
||||
## Attributes Reference
|
||||
|
||||
* `droplets` - A list of Droplets satisfying any `filter` and `sort` criteria. Each Droplet has the following attributes:
|
||||
|
||||
- `id` - The ID of the Droplet.
|
||||
- `urn` - The uniform resource name of the Droplet
|
||||
- `region` - The region the Droplet is running in.
|
||||
- `image` - The Droplet image ID or slug.
|
||||
- `size` - The unique slug that identifies the type of Droplet.
|
||||
- `disk` - The size of the Droplet's disk in GB.
|
||||
- `vcpus` - The number of the Droplet's virtual CPUs.
|
||||
- `memory` - The amount of the Droplet's memory in MB.
|
||||
- `price_hourly` - Droplet hourly price.
|
||||
- `price_monthly` - Droplet monthly price.
|
||||
- `status` - The status of the Droplet.
|
||||
- `locked` - Whether the Droplet is locked.
|
||||
- `ipv6_address` - The Droplet's public IPv6 address
|
||||
- `ipv6_address_private` - The Droplet's private IPv6 address
|
||||
- `ipv4_address` - The Droplet's public IPv4 address
|
||||
- `ipv4_address_private` - The Droplet's private IPv4 address
|
||||
- `backups` - Whether backups are enabled.
|
||||
- `ipv6` - Whether IPv6 is enabled.
|
||||
- `private_networking` - Whether private networks are enabled.
|
||||
- `monitoring` - Whether monitoring agent is installed.
|
||||
- `volume_ids` - List of the IDs of each volumes attached to the Droplet.
|
||||
- `tags` - A list of the tags associated to the Droplet.
|
||||
- `vpc_uuid` - The ID of the VPC where the Droplet is located.
|
Loading…
Reference in New Issue