provider/aws: New Resource aws_ebs_snapshot (#10017)

* provider/aws: Add ability to create aws_ebs_snapshot

```
% make testacc TEST=./builtin/providers/aws TESTARGS='-run=TestAccAWSEBSSnapshot_'
==> Checking that code complies with gofmt requirements...
go generate $(go list ./... | grep -v /terraform/vendor/)
2016/11/10 14:18:36 Generated command/internal_plugin_list.go
TF_ACC=1 go test ./builtin/providers/aws -v -run=TestAccAWSEBSSnapshot_
-timeout 120m
=== RUN   TestAccAWSEBSSnapshot_basic
--- PASS: TestAccAWSEBSSnapshot_basic (31.56s)
=== RUN   TestAccAWSEBSSnapshot_withDescription
--- PASS: TestAccAWSEBSSnapshot_withDescription (189.35s)
PASS
ok      github.com/hashicorp/terraform/builtin/providers/aws220.928s
```

* docs/aws: Addition of the docs for aws_ebs_snapshot resource

* provider/aws: Creation of shared schema funcs for common AWS data source
patterns

* provider/aws: Create aws_ebs_snapshot datasource

Fixes #8828

This data source will use a number of filters, owner_ids, snapshot_ids
and restorable_by_user_ids in order to find the correct snapshot. The
data source has no real use case for most_recent and will error on no
snapshots found or greater than 1 snapshot found

```
% make testacc TEST=./builtin/providers/aws TESTARGS='-run=TestAccAWSEbsSnapshotDataSource_'
==> Checking that code complies with gofmt requirements...
go generate $(go list ./... | grep -v /terraform/vendor/)
2016/11/10 14:34:33 Generated command/internal_plugin_list.go
TF_ACC=1 go test ./builtin/providers/aws -v
-run=TestAccAWSEbsSnapshotDataSource_ -timeout 120m
=== RUN   TestAccAWSEbsSnapshotDataSource_basic
--- PASS: TestAccAWSEbsSnapshotDataSource_basic (192.66s)
=== RUN   TestAccAWSEbsSnapshotDataSource_multipleFilters
--- PASS: TestAccAWSEbsSnapshotDataSource_multipleFilters (33.84s)
PASS
ok      github.com/hashicorp/terraform/builtin/providers/aws226.522s
```

* docs/aws: Addition of docs for the aws_ebs_snapshot data source

Adds the new resource `aws_ebs_snapshot`
This commit is contained in:
Paul Stack 2016-11-21 12:40:22 +02:00 committed by GitHub
parent a79092b86c
commit 7fde952d02
11 changed files with 701 additions and 168 deletions

View File

@ -8,7 +8,6 @@ import (
"sort"
"time"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/hashicorp/terraform/helper/hashcode"
"github.com/hashicorp/terraform/helper/schema"
@ -19,31 +18,13 @@ func dataSourceAwsAmi() *schema.Resource {
Read: dataSourceAwsAmiRead,
Schema: map[string]*schema.Schema{
"filter": dataSourceFiltersSchema(),
"executable_users": {
Type: schema.TypeList,
Optional: true,
ForceNew: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
"filter": {
Type: schema.TypeSet,
Optional: true,
ForceNew: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Required: true,
},
"values": {
Type: schema.TypeList,
Required: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
},
},
},
"name_regex": {
Type: schema.TypeString,
Optional: true,
@ -186,23 +167,7 @@ func dataSourceAwsAmi() *schema.Resource {
Type: schema.TypeMap,
Computed: true,
},
"tags": {
Type: schema.TypeSet,
Computed: true,
Set: amiTagsHash,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"key": {
Type: schema.TypeString,
Computed: true,
},
"value": {
Type: schema.TypeString,
Computed: true,
},
},
},
},
"tags": dataSourceTagsSchema(),
},
}
}
@ -225,7 +190,7 @@ func dataSourceAwsAmiRead(d *schema.ResourceData, meta interface{}) error {
params.ExecutableUsers = expandStringList(executableUsers.([]interface{}))
}
if filtersOk {
params.Filters = buildAmiFilters(filters.(*schema.Set))
params.Filters = buildAwsDataSourceFilters(filters.(*schema.Set))
}
if ownersOk {
params.Owners = expandStringList(owners.([]interface{}))
@ -280,23 +245,6 @@ func dataSourceAwsAmiRead(d *schema.ResourceData, meta interface{}) error {
return amiDescriptionAttributes(d, image)
}
// Build a slice of AMI filter options from the filters provided.
func buildAmiFilters(set *schema.Set) []*ec2.Filter {
var filters []*ec2.Filter
for _, v := range set.List() {
m := v.(map[string]interface{})
var filterValues []*string
for _, e := range m["values"].([]interface{}) {
filterValues = append(filterValues, aws.String(e.(string)))
}
filters = append(filters, &ec2.Filter{
Name: aws.String(m["name"].(string)),
Values: filterValues,
})
}
return filters
}
type imageSort []*ec2.Image
func (a imageSort) Len() int { return len(a) }
@ -361,7 +309,7 @@ func amiDescriptionAttributes(d *schema.ResourceData, image *ec2.Image) error {
if err := d.Set("state_reason", amiStateReason(image.StateReason)); err != nil {
return err
}
if err := d.Set("tags", amiTags(image.Tags)); err != nil {
if err := d.Set("tags", dataSourceTags(image.Tags)); err != nil {
return err
}
return nil
@ -433,21 +381,6 @@ func amiStateReason(m *ec2.StateReason) map[string]interface{} {
return s
}
// Returns a set of tags.
func amiTags(m []*ec2.Tag) *schema.Set {
s := &schema.Set{
F: amiTagsHash,
}
for _, v := range m {
tag := map[string]interface{}{
"key": *v.Key,
"value": *v.Value,
}
s.Add(tag)
}
return s
}
// Generates a hash for the set hash function used by the block_device_mappings
// attribute.
func amiBlockDeviceMappingHash(v interface{}) int {
@ -488,17 +421,6 @@ func amiProductCodesHash(v interface{}) int {
return hashcode.String(buf.String())
}
// Generates a hash for the set hash function used by the tags
// attribute.
func amiTagsHash(v interface{}) int {
var buf bytes.Buffer
m := v.(map[string]interface{})
// All keys added in alphabetical order.
buf.WriteString(fmt.Sprintf("%s-", m["key"].(string)))
buf.WriteString(fmt.Sprintf("%s-", m["value"].(string)))
return hashcode.String(buf.String())
}
func validateNameRegex(v interface{}, k string) (ws []string, errors []error) {
value := v.(string)

View File

@ -0,0 +1,91 @@
package aws
import (
"bytes"
"fmt"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/hashicorp/terraform/helper/hashcode"
"github.com/hashicorp/terraform/helper/schema"
)
func dataSourceTagsHash(v interface{}) int {
var buf bytes.Buffer
m := v.(map[string]interface{})
buf.WriteString(fmt.Sprintf("%s-", m["key"].(string)))
buf.WriteString(fmt.Sprintf("%s-", m["value"].(string)))
return hashcode.String(buf.String())
}
func dataSourceTags(m []*ec2.Tag) *schema.Set {
s := &schema.Set{
F: dataSourceTagsHash,
}
for _, v := range m {
tag := map[string]interface{}{
"key": *v.Key,
"value": *v.Value,
}
s.Add(tag)
}
return s
}
func buildAwsDataSourceFilters(set *schema.Set) []*ec2.Filter {
var filters []*ec2.Filter
for _, v := range set.List() {
m := v.(map[string]interface{})
var filterValues []*string
for _, e := range m["values"].([]interface{}) {
filterValues = append(filterValues, aws.String(e.(string)))
}
filters = append(filters, &ec2.Filter{
Name: aws.String(m["name"].(string)),
Values: filterValues,
})
}
return filters
}
func dataSourceFiltersSchema() *schema.Schema {
return &schema.Schema{
Type: schema.TypeSet,
Optional: true,
ForceNew: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Required: true,
},
"values": {
Type: schema.TypeList,
Required: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
},
},
}
}
func dataSourceTagsSchema() *schema.Schema {
return &schema.Schema{
Type: schema.TypeSet,
Computed: true,
Set: dataSourceTagsHash,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"key": {
Type: schema.TypeString,
Computed: true,
},
"value": {
Type: schema.TypeString,
Computed: true,
},
},
},
}
}

View File

@ -0,0 +1,143 @@
package aws
import (
"fmt"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/hashicorp/terraform/helper/schema"
)
func dataSourceAwsEbsSnapshot() *schema.Resource {
return &schema.Resource{
Read: dataSourceAwsEbsSnapshotRead,
Schema: map[string]*schema.Schema{
//selection criteria
"filter": dataSourceFiltersSchema(),
"owners": {
Type: schema.TypeList,
Optional: true,
ForceNew: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
"snapshot_ids": {
Type: schema.TypeList,
Optional: true,
ForceNew: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
"restorable_by_user_ids": {
Type: schema.TypeList,
Optional: true,
ForceNew: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
//Computed values returned
"snapshot_id": {
Type: schema.TypeString,
Computed: true,
},
"volume_id": {
Type: schema.TypeString,
Computed: true,
},
"state": {
Type: schema.TypeString,
Computed: true,
},
"owner_id": {
Type: schema.TypeString,
Computed: true,
},
"owner_alias": {
Type: schema.TypeString,
Computed: true,
},
"encrypted": {
Type: schema.TypeBool,
Computed: true,
},
"description": {
Type: schema.TypeString,
Computed: true,
},
"volume_size": {
Type: schema.TypeInt,
Computed: true,
},
"kms_key_id": {
Type: schema.TypeString,
Computed: true,
},
"data_encryption_key_id": {
Type: schema.TypeString,
Computed: true,
},
"tags": dataSourceTagsSchema(),
},
}
}
func dataSourceAwsEbsSnapshotRead(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).ec2conn
restorableUsers, restorableUsersOk := d.GetOk("restorable_by_user_ids")
filters, filtersOk := d.GetOk("filter")
snapshotIds, snapshotIdsOk := d.GetOk("snapshot_ids")
owners, ownersOk := d.GetOk("owners")
if restorableUsers == false && filtersOk == false && snapshotIds == false && ownersOk == false {
return fmt.Errorf("One of snapshot_ids, filters, restorable_by_user_ids, or owners must be assigned")
}
params := &ec2.DescribeSnapshotsInput{}
if restorableUsersOk {
params.RestorableByUserIds = expandStringList(restorableUsers.([]interface{}))
}
if filtersOk {
params.Filters = buildAwsDataSourceFilters(filters.(*schema.Set))
}
if ownersOk {
params.OwnerIds = expandStringList(owners.([]interface{}))
}
if snapshotIdsOk {
params.SnapshotIds = expandStringList(snapshotIds.([]interface{}))
}
resp, err := conn.DescribeSnapshots(params)
if err != nil {
return err
}
if len(resp.Snapshots) < 1 {
return fmt.Errorf("Your query returned no results. Please change your search criteria and try again.")
}
if len(resp.Snapshots) > 1 {
return fmt.Errorf("Your query returned more than one result. Please try a more specific search criteria.")
}
//Single Snapshot found so set to state
return snapshotDescriptionAttributes(d, resp.Snapshots[0])
}
func snapshotDescriptionAttributes(d *schema.ResourceData, snapshot *ec2.Snapshot) error {
d.SetId(*snapshot.SnapshotId)
d.Set("snapshot_id", snapshot.SnapshotId)
d.Set("volume_id", snapshot.VolumeId)
d.Set("data_encryption_key_id", snapshot.DataEncryptionKeyId)
d.Set("description", snapshot.Description)
d.Set("encrypted", snapshot.Encrypted)
d.Set("kms_key_id", snapshot.KmsKeyId)
d.Set("volume_size", snapshot.VolumeSize)
d.Set("state", snapshot.State)
d.Set("owner_id", snapshot.OwnerId)
d.Set("owner_alias", snapshot.OwnerAlias)
if err := d.Set("tags", dataSourceTags(snapshot.Tags)); err != nil {
return err
}
return nil
}

View File

@ -0,0 +1,97 @@
package aws
import (
"fmt"
"testing"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
)
func TestAccAWSEbsSnapshotDataSource_basic(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
{
Config: testAccCheckAwsEbsSnapshotDataSourceConfig,
Check: resource.ComposeTestCheckFunc(
testAccCheckAwsEbsSnapshotDataSourceID("data.aws_ebs_snapshot.snapshot"),
resource.TestCheckResourceAttr("data.aws_ebs_snapshot.snapshot", "volume_size", "40"),
),
},
},
})
}
func TestAccAWSEbsSnapshotDataSource_multipleFilters(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
{
Config: testAccCheckAwsEbsSnapshotDataSourceConfigWithMultipleFilters,
Check: resource.ComposeTestCheckFunc(
testAccCheckAwsEbsSnapshotDataSourceID("data.aws_ebs_snapshot.snapshot"),
resource.TestCheckResourceAttr("data.aws_ebs_snapshot.snapshot", "volume_size", "10"),
),
},
},
})
}
func testAccCheckAwsEbsSnapshotDataSourceID(n string) resource.TestCheckFunc {
return func(s *terraform.State) error {
rs, ok := s.RootModule().Resources[n]
if !ok {
return fmt.Errorf("Can't find Volume data source: %s", n)
}
if rs.Primary.ID == "" {
return fmt.Errorf("Snapshot data source ID not set")
}
return nil
}
}
const testAccCheckAwsEbsSnapshotDataSourceConfig = `
resource "aws_ebs_volume" "example" {
availability_zone = "us-west-2a"
type = "gp2"
size = 40
tags {
Name = "External Volume"
}
}
resource "aws_ebs_snapshot" "snapshot" {
volume_id = "${aws_ebs_volume.example.id}"
}
data "aws_ebs_snapshot" "snapshot" {
snapshot_ids = ["${aws_ebs_snapshot.snapshot.id}"]
}
`
const testAccCheckAwsEbsSnapshotDataSourceConfigWithMultipleFilters = `
resource "aws_ebs_volume" "external1" {
availability_zone = "us-west-2a"
type = "gp2"
size = 10
tags {
Name = "External Volume 1"
}
}
resource "aws_ebs_snapshot" "snapshot" {
volume_id = "${aws_ebs_volume.external1.id}"
}
data "aws_ebs_snapshot" "snapshot" {
snapshot_ids = ["${aws_ebs_snapshot.snapshot.id}"]
filter {
name = "volume-size"
values = ["10"]
}
}
`

View File

@ -1,15 +1,12 @@
package aws
import (
"bytes"
"fmt"
"log"
"sort"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/davecgh/go-spew/spew"
"github.com/hashicorp/terraform/helper/hashcode"
"github.com/hashicorp/terraform/helper/schema"
)
@ -18,25 +15,7 @@ func dataSourceAwsEbsVolume() *schema.Resource {
Read: dataSourceAwsEbsVolumeRead,
Schema: map[string]*schema.Schema{
"filter": {
Type: schema.TypeSet,
Optional: true,
ForceNew: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Required: true,
},
"values": {
Type: schema.TypeList,
Required: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
},
},
},
"filter": dataSourceFiltersSchema(),
"most_recent": {
Type: schema.TypeBool,
Optional: true,
@ -75,23 +54,7 @@ func dataSourceAwsEbsVolume() *schema.Resource {
Type: schema.TypeString,
Computed: true,
},
"tags": {
Type: schema.TypeSet,
Computed: true,
Set: volumeTagsHash,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"key": {
Type: schema.TypeString,
Computed: true,
},
"value": {
Type: schema.TypeString,
Computed: true,
},
},
},
},
"tags": dataSourceTagsSchema(),
},
}
}
@ -103,7 +66,7 @@ func dataSourceAwsEbsVolumeRead(d *schema.ResourceData, meta interface{}) error
params := &ec2.DescribeVolumesInput{}
if filtersOk {
params.Filters = buildVolumeFilters(filters.(*schema.Set))
params.Filters = buildAwsDataSourceFilters(filters.(*schema.Set))
}
resp, err := conn.DescribeVolumes(params)
@ -138,22 +101,6 @@ func dataSourceAwsEbsVolumeRead(d *schema.ResourceData, meta interface{}) error
return volumeDescriptionAttributes(d, volume)
}
func buildVolumeFilters(set *schema.Set) []*ec2.Filter {
var filters []*ec2.Filter
for _, v := range set.List() {
m := v.(map[string]interface{})
var filterValues []*string
for _, e := range m["values"].([]interface{}) {
filterValues = append(filterValues, aws.String(e.(string)))
}
filters = append(filters, &ec2.Filter{
Name: aws.String(m["name"].(string)),
Values: filterValues,
})
}
return filters
}
type volumeSort []*ec2.Volume
func (a volumeSort) Len() int { return len(a) }
@ -181,31 +128,9 @@ func volumeDescriptionAttributes(d *schema.ResourceData, volume *ec2.Volume) err
d.Set("snapshot_id", volume.SnapshotId)
d.Set("volume_type", volume.VolumeType)
if err := d.Set("tags", volumeTags(volume.Tags)); err != nil {
if err := d.Set("tags", dataSourceTags(volume.Tags)); err != nil {
return err
}
return nil
}
func volumeTags(m []*ec2.Tag) *schema.Set {
s := &schema.Set{
F: volumeTagsHash,
}
for _, v := range m {
tag := map[string]interface{}{
"key": *v.Key,
"value": *v.Value,
}
s.Add(tag)
}
return s
}
func volumeTagsHash(v interface{}) int {
var buf bytes.Buffer
m := v.(map[string]interface{})
buf.WriteString(fmt.Sprintf("%s-", m["key"].(string)))
buf.WriteString(fmt.Sprintf("%s-", m["value"].(string)))
return hashcode.String(buf.String())
}

View File

@ -152,6 +152,7 @@ func Provider() terraform.ResourceProvider {
"aws_billing_service_account": dataSourceAwsBillingServiceAccount(),
"aws_caller_identity": dataSourceAwsCallerIdentity(),
"aws_cloudformation_stack": dataSourceAwsCloudFormationStack(),
"aws_ebs_snapshot": dataSourceAwsEbsSnapshot(),
"aws_ebs_volume": dataSourceAwsEbsVolume(),
"aws_ecs_container_definition": dataSourceAwsEcsContainerDefinition(),
"aws_elb_service_account": dataSourceAwsElbServiceAccount(),
@ -223,6 +224,7 @@ func Provider() terraform.ResourceProvider {
"aws_db_subnet_group": resourceAwsDbSubnetGroup(),
"aws_directory_service_directory": resourceAwsDirectoryServiceDirectory(),
"aws_dynamodb_table": resourceAwsDynamoDbTable(),
"aws_ebs_snapshot": resourceAwsEbsSnapshot(),
"aws_ebs_volume": resourceAwsEbsVolume(),
"aws_ecr_repository": resourceAwsEcrRepository(),
"aws_ecr_repository_policy": resourceAwsEcrRepositoryPolicy(),

View File

@ -0,0 +1,145 @@
package aws
import (
"fmt"
"log"
"time"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/helper/schema"
)
func resourceAwsEbsSnapshot() *schema.Resource {
return &schema.Resource{
Create: resourceAwsEbsSnapshotCreate,
Read: resourceAwsEbsSnapshotRead,
Delete: resourceAwsEbsSnapshotDelete,
Schema: map[string]*schema.Schema{
"volume_id": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"description": {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
},
"owner_id": {
Type: schema.TypeString,
Computed: true,
},
"owner_alias": {
Type: schema.TypeString,
Computed: true,
},
"encrypted": {
Type: schema.TypeBool,
Computed: true,
},
"volume_size": {
Type: schema.TypeInt,
Computed: true,
},
"kms_key_id": {
Type: schema.TypeString,
Computed: true,
},
"data_encryption_key_id": {
Type: schema.TypeString,
Computed: true,
},
},
}
}
func resourceAwsEbsSnapshotCreate(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).ec2conn
request := &ec2.CreateSnapshotInput{
VolumeId: aws.String(d.Get("volume_id").(string)),
}
if v, ok := d.GetOk("description"); ok {
request.Description = aws.String(v.(string))
}
res, err := conn.CreateSnapshot(request)
if err != nil {
return err
}
d.SetId(*res.SnapshotId)
err = resourceAwsEbsSnapshotWaitForAvailable(d.Id(), conn)
if err != nil {
return err
}
return resourceAwsEbsSnapshotRead(d, meta)
}
func resourceAwsEbsSnapshotRead(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).ec2conn
req := &ec2.DescribeSnapshotsInput{
SnapshotIds: []*string{aws.String(d.Id())},
}
res, err := conn.DescribeSnapshots(req)
if ec2err, ok := err.(awserr.Error); ok && ec2err.Code() == "InvalidSnapshotID.NotFound" {
log.Printf("Snapshot %q Not found - removing from state", d.Id())
d.SetId("")
return nil
}
snapshot := res.Snapshots[0]
d.Set("description", snapshot.Description)
d.Set("owner_id", snapshot.OwnerId)
d.Set("encrypted", snapshot.Encrypted)
d.Set("owner_alias", snapshot.OwnerAlias)
d.Set("volume_id", snapshot.VolumeId)
d.Set("data_encryption_key_id", snapshot.DataEncryptionKeyId)
d.Set("kms_keey_id", snapshot.KmsKeyId)
d.Set("volume_size", snapshot.VolumeSize)
return nil
}
func resourceAwsEbsSnapshotDelete(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).ec2conn
return resource.Retry(5*time.Minute, func() *resource.RetryError {
request := &ec2.DeleteSnapshotInput{
SnapshotId: aws.String(d.Id()),
}
_, err := conn.DeleteSnapshot(request)
if err == nil {
return nil
}
ebsErr, ok := err.(awserr.Error)
if ebsErr.Code() == "SnapshotInUse" {
return resource.RetryableError(fmt.Errorf("EBS SnapshotInUse - trying again while it detaches"))
}
if !ok {
return resource.NonRetryableError(err)
}
return resource.NonRetryableError(err)
})
}
func resourceAwsEbsSnapshotWaitForAvailable(id string, conn *ec2.EC2) error {
log.Printf("Waiting for Snapshot %s to become available...", id)
req := &ec2.DescribeSnapshotsInput{
SnapshotIds: []*string{aws.String(id)},
}
err := conn.WaitUntilSnapshotCompleted(req)
return err
}

View File

@ -0,0 +1,95 @@
package aws
import (
"fmt"
"testing"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
)
func TestAccAWSEBSSnapshot_basic(t *testing.T) {
var v ec2.Snapshot
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
{
Config: testAccAwsEbsSnapshotConfig,
Check: resource.ComposeTestCheckFunc(
testAccCheckSnapshotExists("aws_ebs_snapshot.test", &v),
),
},
},
})
}
func TestAccAWSEBSSnapshot_withDescription(t *testing.T) {
var v ec2.Snapshot
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
{
Config: testAccAwsEbsSnapshotConfigWithDescription,
Check: resource.ComposeTestCheckFunc(
testAccCheckSnapshotExists("aws_ebs_snapshot.test", &v),
resource.TestCheckResourceAttr("aws_ebs_snapshot.test", "description", "EBS Snapshot Acceptance Test"),
),
},
},
})
}
func testAccCheckSnapshotExists(n string, v *ec2.Snapshot) resource.TestCheckFunc {
return func(s *terraform.State) error {
rs, ok := s.RootModule().Resources[n]
if !ok {
return fmt.Errorf("Not found: %s", n)
}
if rs.Primary.ID == "" {
return fmt.Errorf("No ID is set")
}
conn := testAccProvider.Meta().(*AWSClient).ec2conn
request := &ec2.DescribeSnapshotsInput{
SnapshotIds: []*string{aws.String(rs.Primary.ID)},
}
response, err := conn.DescribeSnapshots(request)
if err == nil {
if response.Snapshots != nil && len(response.Snapshots) > 0 {
*v = *response.Snapshots[0]
return nil
}
}
return fmt.Errorf("Error finding EC2 Snapshot %s", rs.Primary.ID)
}
}
const testAccAwsEbsSnapshotConfig = `
resource "aws_ebs_volume" "test" {
availability_zone = "us-west-2a"
size = 1
}
resource "aws_ebs_snapshot" "test" {
volume_id = "${aws_ebs_volume.test.id}"
}
`
const testAccAwsEbsSnapshotConfigWithDescription = `
resource "aws_ebs_volume" "description_test" {
availability_zone = "us-west-2a"
size = 1
}
resource "aws_ebs_snapshot" "test" {
volume_id = "${aws_ebs_volume.description_test.id}"
description = "EBS Snapshot Acceptance Test"
}
`

View File

@ -0,0 +1,61 @@
---
layout: "aws"
page_title: "AWS: aws_ebs_snapshot"
sidebar_current: "docs-aws-datasource-ebs-snapshot"
description: |-
Get information on an EBS Snapshot.
---
# aws\_ebs\_snapshot
Use this data source to get information about an EBS Snapshot for use when provisioning EBS Volumes
## Example Usage
```
data "aws_ebs_snapshot" "ebs_volume" {
owners = ["self"]
filter {
name = "volume-size"
values = ["40"]
}
filter {
name = "tag:Name"
values = ["Example"]
}
}
```
## Argument Reference
The following arguments are supported:
* `owners` - (Optional) Returns the snapshots owned by the specified owner id. Multiple owners can be specified.
* `snapshot_ids` - (Optional) Returns information on a specific snapshot_id.
* `restorable_by_user_ids` - (Optional) One or more AWS accounts IDs that can create volumes from the snapshot.
* `filter` - (Optional) One or more name/value pairs to filter off of. There are
several valid keys, for a full reference, check out
[describe-volumes in the AWS CLI reference][1].
## Attributes Reference
The following attributes are exported:
* `id` - The snapshot ID (e.g. snap-59fcb34e).
* `snapshot_id` - The snapshot ID (e.g. snap-59fcb34e).
* `description` - A description for the snapshot
* `owner_id` - The AWS account ID of the EBS snapshot owner.
* `owner_alias` - Value from an Amazon-maintained list (`amazon`, `aws-marketplace`, `microsoft`) of snapshot owners.
* `volume_id` - The volume ID (e.g. vol-59fcb34e).
* `encrypted` - Whether the snapshot is encrypted.
* `volume_size` - The size of the drive in GiBs.
* `kms_key_id` - The ARN for the KMS encryption key.
* `data_encryption_key_id` - The data encryption key identifier for the snapshot.
* `state` - The snapshot state.
* `tags` - A mapping of tags for the resource.
[1]: http://docs.aws.amazon.com/cli/latest/reference/ec2/describe-snapshots.html

View File

@ -0,0 +1,48 @@
---
layout: "aws"
page_title: "AWS: aws_ebs_snapshot"
sidebar_current: "docs-aws-resource-ebs-snapshot"
description: |-
Provides an elastic block storage snapshot resource.
---
# aws\_ebs\_snapshot
Creates a Snapshot of an EBS Volume.
## Example Usage
```
resource "aws_ebs_volume" "example" {
availability_zone = "us-west-2a"
size = 40
tags {
Name = "HelloWorld"
}
}
resource "aws_ebs_snapshot" "example_snapshot" {
volume_id = "${aws_ebs_volume.example.id}"
}
```
## Argument Reference
The following arguments are supported:
* `volume_id` - (Required) The Volume ID of which to make a snapshot.
* `description` - (Optional) A description of what the snapshot is.
## Attributes Reference
The following attributes are exported:
* `id` - The snapshot ID (e.g. snap-59fcb34e).
* `owner_id` - The AWS account ID of the EBS snapshot owner.
* `owner_alias` - Value from an Amazon-maintained list (`amazon`, `aws-marketplace`, `microsoft`) of snapshot owners.
* `encrypted` - Whether the snapshot is encrypted.
* `volume_size` - The size of the drive in GiBs.
* `kms_key_id` - The ARN for the KMS encryption key.
* `data_encryption_key_id` - The data encryption key identifier for the snapshot.
* `tags` - A mapping of tags for the resource.

View File

@ -20,6 +20,7 @@
<li<%= sidebar_current("docs-aws-datasource-alb") %>>
<a href="/docs/providers/aws/d/alb.html">aws_alb</a>
</li>
<li<%= sidebar_current("docs-aws-datasource-ami") %>>
<a href="/docs/providers/aws/d/ami.html">aws_ami</a>
</li>
@ -38,6 +39,9 @@
<li<%= sidebar_current("docs-aws-datasource-cloudformation-stack") %>>
<a href="/docs/providers/aws/d/cloudformation_stack.html">aws_cloudformation_stack</a>
</li>
<li<%= sidebar_current("docs-aws-datasource-ebs-snapshot") %>>
<a href="/docs/providers/aws/d/ebs_snapshot.html">aws_ebs_snapshot</a>
</li>
<li<%= sidebar_current("docs-aws-datasource-ebs-volume") %>>
<a href="/docs/providers/aws/d/ebs_volume.html">aws_ebs_volume</a>
</li>
@ -304,10 +308,6 @@
<a href="/docs/providers/aws/r/autoscaling_group.html">aws_autoscaling_group</a>
</li>
<li<%= sidebar_current("docs-aws-resource-autoscaling-attachment") %>>
<a href="/docs/providers/aws/r/autoscaling_attachment.html">aws_autoscaling_attachment</a>
</li>
<li<%= sidebar_current("docs-aws-resource-autoscaling-lifecycle-hook") %>>
<a href="/docs/providers/aws/r/autoscaling_lifecycle_hooks.html">aws_autoscaling_lifecycle_hook</a>
</li>
@ -324,6 +324,10 @@
<a href="/docs/providers/aws/r/autoscaling_schedule.html">aws_autoscaling_schedule</a>
</li>
<li<%= sidebar_current("docs-aws-resource-ebs-snapshot") %>>
<a href="/docs/providers/aws/r/ebs_snapshot.html">aws_ebs_snapshot</a>
</li>
<li<%= sidebar_current("docs-aws-resource-ebs-volume") %>>
<a href="/docs/providers/aws/r/ebs_volume.html">aws_ebs_volume</a>
</li>
@ -819,11 +823,11 @@
<li<%= sidebar_current("docs-aws-resource-waf-webacl") %>>
<a href="/docs/providers/aws/r/waf_web_acl.html">aws_waf_web_acl</a>
</li>
<li<%= sidebar_current("docs-aws-resource-waf-bytematchset") %>>
<a href="/docs/providers/aws/r/waf_byte_match_set.html">aws_waf_byte_match_set</a>
</li>
<li<%= sidebar_current("docs-aws-resource-waf-size-constraint-set") %>>
<a href="/docs/providers/aws/r/waf_size_constraint_set.html">aws_waf_size_constraint_set</a>
</li>
@ -835,7 +839,7 @@
<li<%= sidebar_current("docs-aws-resource-waf-ipset") %>>
<a href="/docs/providers/aws/r/waf_ipset.html">aws_waf_ipset</a>
</li>
<li<%= sidebar_current("docs-aws-resource-waf-xss-match-set") %>>
<a href="/docs/providers/aws/r/waf_xss_match_set.html">aws_waf_xss_match_set</a>
</li>