Skip to content

Commit

Permalink
Support GPU Droplets in Droplet data sources (#1256)
Browse files Browse the repository at this point in the history
* Vendor latest godo

* datasource_droplets: support listing GPU Droplets.

* datasource_droplet: support finding GPU Droplets by name.

* Add documentation.
  • Loading branch information
andrewsomething authored Oct 25, 2024
1 parent bf9cce3 commit 8e91e73
Show file tree
Hide file tree
Showing 19 changed files with 765 additions and 25 deletions.
14 changes: 13 additions & 1 deletion digitalocean/droplet/datasource_droplet.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@ func DataSourceDigitalOceanDroplet() *schema.Resource {
recordSchema["id"].Optional = true
recordSchema["name"].ExactlyOneOf = []string{"id", "tag", "name"}
recordSchema["name"].Optional = true
recordSchema["gpu"] = &schema.Schema{
Type: schema.TypeBool,
Optional: true,
Default: false,
ConflictsWith: []string{"tag"},
}

recordSchema["tag"] = &schema.Schema{
Type: schema.TypeString,
Expand Down Expand Up @@ -64,7 +70,13 @@ func dataSourceDigitalOceanDropletRead(ctx context.Context, d *schema.ResourceDa

foundDroplet = *droplet
} else if v, ok := d.GetOk("name"); ok {
dropletList, err := getDigitalOceanDroplets(meta, nil)
gpus := d.Get("gpu").(bool)
extra := make(map[string]interface{})
if gpus {
extra["gpus"] = true
}

dropletList, err := getDigitalOceanDroplets(meta, extra)
if err != nil {
return diag.FromErr(err)
}
Expand Down
64 changes: 64 additions & 0 deletions digitalocean/droplet/datasource_droplet_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@ package droplet_test
import (
"context"
"fmt"
"os"
"strconv"
"testing"

"github.com/digitalocean/godo"
"github.com/digitalocean/terraform-provider-digitalocean/digitalocean/acceptance"
"github.com/digitalocean/terraform-provider-digitalocean/digitalocean/config"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
)
Expand Down Expand Up @@ -52,6 +54,52 @@ data "digitalocean_droplet" "foobar" {
})
}

func TestAccDataSourceDigitalOceanDroplet_GPUByName(t *testing.T) {
runGPU := os.Getenv(runGPUEnvVar)
if runGPU == "" {
t.Skip("'DO_RUN_GPU_TESTS' env var not set; Skipping tests that requires a GPU Droplet")
}

keyName := acceptance.RandomTestName()
publicKeyMaterial, _, err := acctest.RandSSHKeyPair("digitalocean@ssh-acceptance-test")
if err != nil {
t.Fatalf("Cannot generate test SSH key pair: %s", err)
}

var droplet godo.Droplet
name := acceptance.RandomTestName()
resourceConfig := testAccCheckDataSourceDigitalOceanDropletConfig_gpuByName(keyName, publicKeyMaterial, name)
dataSourceConfig := `
data "digitalocean_droplet" "foobar" {
name = digitalocean_droplet.foo.name
gpu = true
}`

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { acceptance.TestAccPreCheck(t) },
ProviderFactories: acceptance.TestAccProviderFactories,
Steps: []resource.TestStep{
{
Config: resourceConfig,
},
{
Config: resourceConfig + dataSourceConfig,
Check: resource.ComposeTestCheckFunc(
testAccCheckDataSourceDigitalOceanDropletExists("data.digitalocean_droplet.foobar", &droplet),
resource.TestCheckResourceAttr(
"data.digitalocean_droplet.foobar", "name", name),
resource.TestCheckResourceAttr(
"data.digitalocean_droplet.foobar", "image", gpuImage),
resource.TestCheckResourceAttr(
"data.digitalocean_droplet.foobar", "region", "tor1"),
resource.TestCheckResourceAttrSet("data.digitalocean_droplet.foobar", "urn"),
resource.TestCheckResourceAttrSet("data.digitalocean_droplet.foobar", "created_at"),
),
},
},
})
}

func TestAccDataSourceDigitalOceanDroplet_BasicById(t *testing.T) {
var droplet godo.Droplet
name := acceptance.RandomTestName()
Expand Down Expand Up @@ -173,6 +221,22 @@ resource "digitalocean_droplet" "foo" {
}`, acceptance.RandomTestName(), name, defaultSize, defaultImage)
}

func testAccCheckDataSourceDigitalOceanDropletConfig_gpuByName(keyName, key, name string) string {
return fmt.Sprintf(`
resource "digitalocean_ssh_key" "foobar" {
name = "%s"
public_key = "%s"
}
resource "digitalocean_droplet" "foo" {
name = "%s"
size = "%s"
image = "%s"
region = "tor1"
ssh_keys = [digitalocean_ssh_key.foobar.id]
}`, keyName, key, name, gpuSize, gpuImage)
}

func testAccCheckDataSourceDigitalOceanDropletConfig_basicById(name string) string {
return fmt.Sprintf(`
resource "digitalocean_droplet" "foo" {
Expand Down
7 changes: 7 additions & 0 deletions digitalocean/droplet/datasource_droplets.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,13 @@ func DataSourceDigitalOceanDroplets() *schema.Resource {
ResultAttributeName: "droplets",
GetRecords: getDigitalOceanDroplets,
FlattenRecord: flattenDigitalOceanDroplet,
ExtraQuerySchema: map[string]*schema.Schema{
"gpus": {
Type: schema.TypeBool,
Optional: true,
Default: false,
},
},
}

return datalist.NewResource(dataListConfig)
Expand Down
66 changes: 66 additions & 0 deletions digitalocean/droplet/datasource_droplets_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@ package droplet_test

import (
"fmt"
"os"
"testing"

"github.com/digitalocean/terraform-provider-digitalocean/digitalocean/acceptance"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
)

Expand Down Expand Up @@ -57,3 +59,67 @@ data "digitalocean_droplets" "result" {
},
})
}

func TestAccDataSourceDigitalOceanDroplets_GPUDroplet(t *testing.T) {
runGPU := os.Getenv(runGPUEnvVar)
if runGPU == "" {
t.Skip("'DO_RUN_GPU_TESTS' env var not set; Skipping tests that requires a GPU Droplet")
}

keyName := acceptance.RandomTestName()
publicKeyMaterial, _, err := acctest.RandSSHKeyPair("digitalocean@ssh-acceptance-test")
if err != nil {
t.Fatalf("Cannot generate test SSH key pair: %s", err)
}

name1 := acceptance.RandomTestName("gpu")
name2 := acceptance.RandomTestName("regular")

resourcesConfig := fmt.Sprintf(`
resource "digitalocean_ssh_key" "foobar" {
name = "%s"
public_key = "%s"
}
resource "digitalocean_droplet" "gpu" {
name = "%s"
size = "%s"
image = "%s"
region = "nyc2"
ssh_keys = [digitalocean_ssh_key.foobar.id]
}
resource "digitalocean_droplet" "regular" {
name = "%s"
size = "%s"
image = "%s"
region = "nyc2"
}
`, keyName, publicKeyMaterial, name1, gpuSize, gpuImage, name2, defaultSize, defaultImage)

datasourceConfig := `
data "digitalocean_droplets" "result" {
gpus = true
}
`
resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { acceptance.TestAccPreCheck(t) },
ProviderFactories: acceptance.TestAccProviderFactories,
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),
resource.TestCheckResourceAttrPair("data.digitalocean_droplets.result", "droplets.0.id", "digitalocean_droplet.gpu", "id"),
),
},
{
Config: resourcesConfig,
},
},
})
}
13 changes: 12 additions & 1 deletion digitalocean/droplet/droplets.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,8 @@ func dropletSchema() map[string]*schema.Schema {
func getDigitalOceanDroplets(meta interface{}, extra map[string]interface{}) ([]interface{}, error) {
client := meta.(*config.CombinedConfig).GodoClient()

gpus, _ := extra["gpus"].(bool)

opts := &godo.ListOptions{
Page: 1,
PerPage: 200,
Expand All @@ -126,7 +128,16 @@ func getDigitalOceanDroplets(meta interface{}, extra map[string]interface{}) ([]
var dropletList []interface{}

for {
droplets, resp, err := client.Droplets.List(context.Background(), opts)
var (
droplets []godo.Droplet
resp *godo.Response
err error
)
if gpus {
droplets, resp, err = client.Droplets.ListWithGPUs(context.Background(), opts)
} else {
droplets, resp, err = client.Droplets.List(context.Background(), opts)
}

if err != nil {
return nil, fmt.Errorf("Error retrieving droplets: %s", err)
Expand Down
4 changes: 4 additions & 0 deletions digitalocean/droplet/resource_droplet_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ import (
const (
defaultSize = "s-1vcpu-1gb"
defaultImage = "ubuntu-22-04-x64"

gpuSize = "gpu-h100x1-80gb"
gpuImage = "gpu-h100x1-base"
runGPUEnvVar = "DO_RUN_GPU_TESTS"
)

func TestAccDigitalOceanDroplet_Basic(t *testing.T) {
Expand Down
4 changes: 4 additions & 0 deletions docs/data-sources/droplet.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@ One of the following arguments must be provided:
* `name` - (Optional) The name of the Droplet.
* `tag` - (Optional) A tag applied to the Droplet.

To include GPU Droplets when searching by name, use:

* `gpu` - (Optional) A boolean value specifying whether or not to search GPU Droplets

## Attributes Reference

The following attributes are exported:
Expand Down
5 changes: 5 additions & 0 deletions docs/data-sources/droplets.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ 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.

By default, only non-GPU Droplets are returned. To list only GPU Droplets, set
the `gpus` attribute to `true`.

Note: You can use the [`digitalocean_droplet`](droplet) data source to obtain metadata
about a single Droplet if you already know the `id`, unique `name`, or unique `tag` to retrieve.

Expand Down Expand Up @@ -50,6 +53,8 @@ data "digitalocean_droplets" "small-with-backups" {

## Argument Reference

* `gpus` - (Optional) A boolean value specifying whether or not to list GPU Droplets

* `filter` - (Optional) Filter the results.
The `filter` block is documented below.

Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ module github.com/digitalocean/terraform-provider-digitalocean

require (
github.com/aws/aws-sdk-go v1.42.18
github.com/digitalocean/godo v1.126.1-0.20241004175533-dfe74ef3d8bb
github.com/digitalocean/godo v1.128.1-0.20241025145008-2654a9d1e887
github.com/hashicorp/awspolicyequivalence v1.5.0
github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320
github.com/hashicorp/go-uuid v1.0.3
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ3
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/digitalocean/godo v1.126.1-0.20241004175533-dfe74ef3d8bb h1:D6/pJ6+5wMkpwaF2HMJqvhlPlxWdlbpKx6bOpy8sbBg=
github.com/digitalocean/godo v1.126.1-0.20241004175533-dfe74ef3d8bb/go.mod h1:PU8JB6I1XYkQIdHFop8lLAY9ojp6M0XcU0TWaQSxbrc=
github.com/digitalocean/godo v1.128.1-0.20241025145008-2654a9d1e887 h1:kdXNbMfHEDbQilcqllKkNrJ85ftyJSvSDpsQvzrhHbg=
github.com/digitalocean/godo v1.128.1-0.20241025145008-2654a9d1e887/go.mod h1:PU8JB6I1XYkQIdHFop8lLAY9ojp6M0XcU0TWaQSxbrc=
github.com/emirpasic/gods v1.12.0 h1:QAUIPSaCu4G+POclxeqb3F+WPpdKqFGlw36+yOzGlrg=
github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
Expand Down
15 changes: 15 additions & 0 deletions vendor/github.com/digitalocean/godo/CHANGELOG.md

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

32 changes: 27 additions & 5 deletions vendor/github.com/digitalocean/godo/apps.gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 8e91e73

Please sign in to comment.