-
Notifications
You must be signed in to change notification settings - Fork 9.7k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add DigitalOcean datasource digitalocean_image
Add a new data source for Digital Ocean that finds snapshots by name. Signed-off-by: Julien Pivotto <roidelapluie@inuits.eu>
- Loading branch information
1 parent
3e8dca1
commit 564c67d
Showing
4 changed files
with
277 additions
and
0 deletions.
There are no files selected for viewing
93 changes: 93 additions & 0 deletions
93
builtin/providers/digitalocean/datasource_digitaloceal_image.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
package digitalocean | ||
|
||
import ( | ||
"fmt" | ||
"strconv" | ||
|
||
"github.com/digitalocean/godo" | ||
"github.com/hashicorp/terraform/helper/schema" | ||
) | ||
|
||
func dataSourceDigitalOceanImage() *schema.Resource { | ||
return &schema.Resource{ | ||
Read: dataSourceDigitalOceanImageRead, | ||
Schema: map[string]*schema.Schema{ | ||
|
||
"name": &schema.Schema{ | ||
Type: schema.TypeString, | ||
Required: true, | ||
Description: "name of the image", | ||
}, | ||
// computed attributes | ||
"image": &schema.Schema{ | ||
Type: schema.TypeString, | ||
Computed: true, | ||
Description: "slug or id of the image", | ||
}, | ||
"min_disk_size": &schema.Schema{ | ||
Type: schema.TypeInt, | ||
Computed: true, | ||
Description: "minimum disk size required by the image", | ||
}, | ||
"private": &schema.Schema{ | ||
Type: schema.TypeBool, | ||
Computed: true, | ||
Description: "Is the image private or non-private", | ||
}, | ||
"regions": &schema.Schema{ | ||
Type: schema.TypeList, | ||
Computed: true, | ||
Description: "list of the regions that the image is available in", | ||
Elem: &schema.Schema{Type: schema.TypeString}, | ||
}, | ||
"type": &schema.Schema{ | ||
Type: schema.TypeString, | ||
Computed: true, | ||
Description: "type of the image", | ||
}, | ||
}, | ||
} | ||
} | ||
|
||
func dataSourceDigitalOceanImageRead(d *schema.ResourceData, meta interface{}) error { | ||
client := meta.(*godo.Client) | ||
|
||
opts := &godo.ListOptions{} | ||
|
||
images, _, err := client.Images.ListUser(opts) | ||
if err != nil { | ||
d.SetId("") | ||
return err | ||
} | ||
image, err := findImageByName(images, d.Get("name").(string)) | ||
|
||
if err != nil { | ||
return err | ||
} | ||
|
||
d.SetId(image.Name) | ||
d.Set("name", image.Name) | ||
d.Set("image", strconv.Itoa(image.ID)) | ||
d.Set("min_disk_size", image.MinDiskSize) | ||
d.Set("private", !image.Public) | ||
d.Set("regions", image.Regions) | ||
d.Set("type", image.Type) | ||
|
||
return nil | ||
} | ||
|
||
func findImageByName(images []godo.Image, name string) (*godo.Image, error) { | ||
results := make([]godo.Image, 0) | ||
for _, v := range images { | ||
if v.Name == name { | ||
results = append(results, v) | ||
} | ||
} | ||
if len(results) == 1 { | ||
return &results[0], nil | ||
} | ||
if len(results) == 0 { | ||
return nil, fmt.Errorf("no user image found with name %s", name) | ||
} | ||
return nil, fmt.Errorf("too many user images found with name %s (found %d, expected 1)", name, len(results)) | ||
} |
122 changes: 122 additions & 0 deletions
122
builtin/providers/digitalocean/datasource_digitaloceal_image_test.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
package digitalocean | ||
|
||
import ( | ||
"fmt" | ||
"log" | ||
"regexp" | ||
"testing" | ||
|
||
"github.com/digitalocean/godo" | ||
"github.com/hashicorp/terraform/helper/acctest" | ||
"github.com/hashicorp/terraform/helper/resource" | ||
"github.com/hashicorp/terraform/terraform" | ||
) | ||
|
||
func TestAccDigitalOceanImage_Basic(t *testing.T) { | ||
var droplet godo.Droplet | ||
var snapshotsId []int | ||
rInt := acctest.RandInt() | ||
|
||
resource.Test(t, resource.TestCase{ | ||
PreCheck: func() { testAccPreCheck(t) }, | ||
Providers: testAccProviders, | ||
CheckDestroy: testAccCheckDigitalOceanDropletDestroy, | ||
Steps: []resource.TestStep{ | ||
{ | ||
Config: testAccCheckDigitalOceanDropletConfig_basic(rInt), | ||
Check: resource.ComposeTestCheckFunc( | ||
testAccCheckDigitalOceanDropletExists("digitalocean_droplet.foobar", &droplet), | ||
takeSnapshotsOfDroplet(rInt, &droplet, &snapshotsId), | ||
), | ||
}, | ||
{ | ||
Config: testAccCheckDigitalOceanImageConfig_basic(rInt, 1), | ||
Check: resource.ComposeTestCheckFunc( | ||
resource.TestCheckResourceAttr( | ||
"data.digitalocean_image.foobar", "name", fmt.Sprintf("snap-%d-1", rInt)), | ||
resource.TestCheckResourceAttr( | ||
"data.digitalocean_image.foobar", "min_disk_size", "20"), | ||
resource.TestCheckResourceAttr( | ||
"data.digitalocean_image.foobar", "private", "true"), | ||
resource.TestCheckResourceAttr( | ||
"data.digitalocean_image.foobar", "type", "snapshot"), | ||
), | ||
}, | ||
{ | ||
Config: testAccCheckDigitalOceanImageConfig_basic(rInt, 0), | ||
ExpectError: regexp.MustCompile(`.*too many user images found with name snap-.*\ .found 2, expected 1.`), | ||
}, | ||
{ | ||
Config: testAccCheckDigitalOceanImageConfig_nonexisting(rInt), | ||
Destroy: false, | ||
ExpectError: regexp.MustCompile(`.*no user image found with name snap-.*-nonexisting`), | ||
}, | ||
{ | ||
Config: " ", | ||
Check: resource.ComposeTestCheckFunc( | ||
deleteSnapshots(&snapshotsId), | ||
), | ||
}, | ||
}, | ||
}) | ||
} | ||
|
||
func takeSnapshotsOfDroplet(rInt int, droplet *godo.Droplet, snapshotsId *[]int) resource.TestCheckFunc { | ||
return func(s *terraform.State) error { | ||
client := testAccProvider.Meta().(*godo.Client) | ||
for i := 0; i < 3; i++ { | ||
err := takeSnapshotOfDroplet(rInt, i%2, droplet) | ||
if err != nil { | ||
return err | ||
} | ||
} | ||
retrieveDroplet, _, err := client.Droplets.Get((*droplet).ID) | ||
if err != nil { | ||
return err | ||
} | ||
*snapshotsId = retrieveDroplet.SnapshotIDs | ||
return nil | ||
} | ||
} | ||
|
||
func takeSnapshotOfDroplet(rInt, sInt int, droplet *godo.Droplet) error { | ||
client := testAccProvider.Meta().(*godo.Client) | ||
action, _, err := client.DropletActions.Snapshot((*droplet).ID, fmt.Sprintf("snap-%d-%d", rInt, sInt)) | ||
if err != nil { | ||
return err | ||
} | ||
waitForAction(client, action) | ||
return nil | ||
} | ||
|
||
func deleteSnapshots(snapshotsId *[]int) resource.TestCheckFunc { | ||
return func(s *terraform.State) error { | ||
log.Printf("XXX Deleting snaps") | ||
client := testAccProvider.Meta().(*godo.Client) | ||
snapshots := *snapshotsId | ||
for _, value := range snapshots { | ||
log.Printf("XXX Deleting %d", value) | ||
_, err := client.Images.Delete(value) | ||
if err != nil { | ||
return err | ||
} | ||
} | ||
return nil | ||
} | ||
} | ||
|
||
func testAccCheckDigitalOceanImageConfig_basic(rInt, sInt int) string { | ||
return fmt.Sprintf(` | ||
data "digitalocean_image" "foobar" { | ||
name = "snap-%d-%d" | ||
} | ||
`, rInt, sInt) | ||
} | ||
|
||
func testAccCheckDigitalOceanImageConfig_nonexisting(rInt int) string { | ||
return fmt.Sprintf(` | ||
data "digitalocean_image" "foobar" { | ||
name = "snap-%d-nonexisting" | ||
} | ||
`, rInt) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
--- | ||
layout: "digitalocean" | ||
page_title: "DigitalOcean: digitalocean_image" | ||
sidebar_current: "docs-do-datasource-image" | ||
description: |- | ||
Get information on an snapshot. | ||
--- | ||
|
||
# digitalocean_image | ||
|
||
Get information on an snapshot images. The aim of this datasource is to enable | ||
you to build droplets based on snapshot names. | ||
|
||
An error is triggered if zero or more than one result is returned by the query. | ||
|
||
## Example Usage | ||
|
||
Get the data about a snapshot: | ||
|
||
```hcl | ||
data "digitalocean_image" "example1" { | ||
name = "example-1.0.0" | ||
} | ||
``` | ||
|
||
Reuse the data about a snapshot to create a droplet: | ||
|
||
```hcl | ||
data "digitalocean_image" "example1" { | ||
name = "example-1.0.0" | ||
} | ||
resource "digitalocean_droplet" "example1" { | ||
image = "${data.digitalocean_image.example1.image}" | ||
name = "example-1" | ||
region = "nyc2" | ||
size = "512mb" | ||
} | ||
``` | ||
|
||
## Argument Reference | ||
|
||
The following arguments are supported: | ||
|
||
* `name` - The name of the image. | ||
|
||
## Attributes Reference | ||
|
||
The following attributes are exported: | ||
|
||
* `name` - See Argument Reference above. | ||
* `image` - The id of the image. | ||
* `min_disk_size`: The minimum 'disk' required for the image. | ||
* `private` - Is image a public image or not. Public images represents | ||
Linux distributions or Application, while non-public images represent | ||
snapshots and backups and are only available within your account. | ||
* `regions`: The regions that the image is available in. | ||
* `size_gigabytes`: The size of the image in gigabytes. | ||
* `type`: Type of the image. Can be "snapshot" or "backup". |