diff --git a/.changelog/17243.txt b/.changelog/17243.txt new file mode 100644 index 00000000000..0d66d523ba5 --- /dev/null +++ b/.changelog/17243.txt @@ -0,0 +1,3 @@ +```release-note:bug +resource/aws_ebs_volume: Allow both `size` and `snapshot_id` attributes to be specified +``` diff --git a/aws/resource_aws_ebs_volume.go b/aws/resource_aws_ebs_volume.go index 47c6ae8122f..6b57529222d 100644 --- a/aws/resource_aws_ebs_volume.go +++ b/aws/resource_aws_ebs_volume.go @@ -65,14 +65,14 @@ func resourceAwsEbsVolume() *schema.Resource { Type: schema.TypeInt, Optional: true, Computed: true, - ExactlyOneOf: []string{"size", "snapshot_id"}, + AtLeastOneOf: []string{"size", "snapshot_id"}, }, "snapshot_id": { Type: schema.TypeString, Optional: true, Computed: true, ForceNew: true, - ExactlyOneOf: []string{"size", "snapshot_id"}, + AtLeastOneOf: []string{"size", "snapshot_id"}, }, "outpost_arn": { Type: schema.TypeString, diff --git a/aws/resource_aws_ebs_volume_test.go b/aws/resource_aws_ebs_volume_test.go index 8550bbebe5e..2d5f2919518 100644 --- a/aws/resource_aws_ebs_volume_test.go +++ b/aws/resource_aws_ebs_volume_test.go @@ -595,6 +595,84 @@ func TestAccAWSEBSVolume_gp3_throughput(t *testing.T) { }) } +func TestAccAWSEBSVolume_snapshotID(t *testing.T) { + var v ec2.Volume + resourceName := "aws_ebs_volume.test" + snapshotResourceName := "aws_ebs_snapshot.test" + rName := acctest.RandomWithPrefix("tf-acc-test") + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + IDRefreshName: resourceName, + Providers: testAccProviders, + CheckDestroy: testAccCheckVolumeDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAwsEbsVolumeConfigSnapshotId(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckVolumeExists(resourceName, &v), + testAccMatchResourceAttrRegionalARN(resourceName, "arn", "ec2", regexp.MustCompile(`volume/vol-.+`)), + resource.TestCheckResourceAttr(resourceName, "encrypted", "false"), + resource.TestCheckResourceAttr(resourceName, "iops", "100"), + resource.TestCheckResourceAttr(resourceName, "kms_key_id", ""), + resource.TestCheckResourceAttr(resourceName, "multi_attach_enabled", "false"), + resource.TestCheckResourceAttr(resourceName, "outpost_arn", ""), + resource.TestCheckResourceAttr(resourceName, "size", "1"), + resource.TestCheckResourceAttrPair(resourceName, "snapshot_id", snapshotResourceName, "id"), + resource.TestCheckResourceAttr(resourceName, "tags.%", "1"), + resource.TestCheckResourceAttr(resourceName, "tags.Name", rName), + resource.TestCheckResourceAttr(resourceName, "throughput", "0"), + resource.TestCheckResourceAttr(resourceName, "type", "gp2"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccAWSEBSVolume_snapshotIDAndSize(t *testing.T) { + var v ec2.Volume + resourceName := "aws_ebs_volume.test" + snapshotResourceName := "aws_ebs_snapshot.test" + rName := acctest.RandomWithPrefix("tf-acc-test") + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + IDRefreshName: resourceName, + Providers: testAccProviders, + CheckDestroy: testAccCheckVolumeDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAwsEbsVolumeConfigSnapshotIdAndSize(rName, 20), + Check: resource.ComposeTestCheckFunc( + testAccCheckVolumeExists(resourceName, &v), + testAccMatchResourceAttrRegionalARN(resourceName, "arn", "ec2", regexp.MustCompile(`volume/vol-.+`)), + resource.TestCheckResourceAttr(resourceName, "encrypted", "false"), + resource.TestCheckResourceAttr(resourceName, "iops", "100"), + resource.TestCheckResourceAttr(resourceName, "kms_key_id", ""), + resource.TestCheckResourceAttr(resourceName, "multi_attach_enabled", "false"), + resource.TestCheckResourceAttr(resourceName, "outpost_arn", ""), + resource.TestCheckResourceAttr(resourceName, "size", "20"), + resource.TestCheckResourceAttrPair(resourceName, "snapshot_id", snapshotResourceName, "id"), + resource.TestCheckResourceAttr(resourceName, "tags.%", "1"), + resource.TestCheckResourceAttr(resourceName, "tags.Name", rName), + resource.TestCheckResourceAttr(resourceName, "throughput", "0"), + resource.TestCheckResourceAttr(resourceName, "type", "gp2"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + func TestAccAWSEBSVolume_disappears(t *testing.T) { var v ec2.Volume resourceName := "aws_ebs_volume.test" @@ -1166,3 +1244,68 @@ resource "aws_ebs_volume" "test" { } `, rName, iops)) } + +func testAccAwsEbsVolumeConfigSnapshotId(rName string) string { + return composeConfig( + testAccAvailableAZsNoOptInConfig(), + fmt.Sprintf(` +resource "aws_ebs_volume" "source" { + availability_zone = data.aws_availability_zones.available.names[0] + size = 1 + + tags = { + Name = %[1]q + } +} + +resource "aws_ebs_snapshot" "test" { + volume_id = aws_ebs_volume.source.id + + tags = { + Name = %[1]q + } +} + +resource "aws_ebs_volume" "test" { + availability_zone = data.aws_availability_zones.available.names[0] + snapshot_id = aws_ebs_snapshot.test.id + + tags = { + Name = %[1]q + } +} +`, rName)) +} + +func testAccAwsEbsVolumeConfigSnapshotIdAndSize(rName string, size int) string { + return composeConfig( + testAccAvailableAZsNoOptInConfig(), + fmt.Sprintf(` +resource "aws_ebs_volume" "source" { + availability_zone = data.aws_availability_zones.available.names[0] + size = 10 + + tags = { + Name = %[1]q + } +} + +resource "aws_ebs_snapshot" "test" { + volume_id = aws_ebs_volume.source.id + + tags = { + Name = %[1]q + } +} + +resource "aws_ebs_volume" "test" { + availability_zone = data.aws_availability_zones.available.names[0] + snapshot_id = aws_ebs_snapshot.test.id + size = %[2]d + + tags = { + Name = %[1]q + } +} +`, rName, size)) +} diff --git a/website/docs/r/ebs_volume.html.markdown b/website/docs/r/ebs_volume.html.markdown index e0c1e716ead..f5746c4142d 100644 --- a/website/docs/r/ebs_volume.html.markdown +++ b/website/docs/r/ebs_volume.html.markdown @@ -23,7 +23,7 @@ resource "aws_ebs_volume" "example" { } ``` -~> **NOTE**: One of `size` or `snapshot_id` is required when specifying an EBS volume +~> **NOTE**: At least one of `size` or `snapshot_id` is required when specifying an EBS volume ## Argument Reference