Skip to content

Commit

Permalink
Merge pull request #22939 from DrFaust92/ami_boot
Browse files Browse the repository at this point in the history
rd/ami - add `boot_mode` and `outpost_arn`
  • Loading branch information
ewbankkit authored Feb 4, 2022
2 parents bb560f7 + 321fdc7 commit 1cac125
Show file tree
Hide file tree
Showing 6 changed files with 145 additions and 0 deletions.
7 changes: 7 additions & 0 deletions .changelog/22939.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
```release-note:enhancement
resource/aws_ami: Add `boot_mode` and `ebs_block_device.outpost_arn` arguments.
```

```release-note:enhancement
data-source/aws_ami: Add `boot_mode` attribute.
```
25 changes: 25 additions & 0 deletions internal/service/ec2/ami.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,12 @@ func ResourceAMI() *schema.Resource {
Type: schema.TypeString,
Computed: true,
},
"boot_mode": {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
ValidateFunc: validation.StringInSlice(ec2.BootModeValues_Values(), false),
},
"description": {
Type: schema.TypeString,
Optional: true,
Expand Down Expand Up @@ -98,6 +104,12 @@ func ResourceAMI() *schema.Resource {
Optional: true,
ForceNew: true,
},
"outpost_arn": {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
ValidateFunc: verify.ValidARN,
},
"snapshot_id": {
Type: schema.TypeString,
Optional: true,
Expand Down Expand Up @@ -276,6 +288,10 @@ func resourceAMICreate(d *schema.ResourceData, meta interface{}) error {
req.RamdiskId = aws.String(ramdiskId)
}

if v := d.Get("boot_mode").(string); v != "" {
req.BootMode = aws.String(v)
}

if v, ok := d.GetOk("ebs_block_device"); ok && v.(*schema.Set).Len() > 0 {
for _, tfMapRaw := range v.(*schema.Set).List() {
tfMap, ok := tfMapRaw.(map[string]interface{})
Expand Down Expand Up @@ -407,6 +423,7 @@ func resourceAMIRead(d *schema.ResourceData, meta interface{}) error {
}

d.Set("architecture", image.Architecture)
d.Set("boot_mode", image.BootMode)
d.Set("description", image.Description)
d.Set("ena_support", image.EnaSupport)
d.Set("hypervisor", image.Hypervisor)
Expand Down Expand Up @@ -633,6 +650,10 @@ func expandEc2BlockDeviceMappingForAmiEbsBlockDevice(tfMap map[string]interface{
apiObject.Ebs.VolumeType = aws.String(v)
}

if v, ok := tfMap["outpost_arn"].(string); ok && v != "" {
apiObject.Ebs.OutpostArn = aws.String(v)
}

return apiObject
}

Expand Down Expand Up @@ -705,6 +726,10 @@ func flattenEc2BlockDeviceMappingForAmiEbsBlockDevice(apiObject *ec2.BlockDevice
tfMap["volume_type"] = aws.StringValue(v)
}

if v := apiObject.Ebs.OutpostArn; v != nil {
tfMap["outpost_arn"] = aws.StringValue(v)
}

return tfMap
}

Expand Down
5 changes: 5 additions & 0 deletions internal/service/ec2/ami_data_source.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,10 @@ func DataSourceAMI() *schema.Resource {
Type: schema.TypeString,
Computed: true,
},
"boot_mode": {
Type: schema.TypeString,
Computed: true,
},
"description": {
Type: schema.TypeString,
Computed: true,
Expand Down Expand Up @@ -268,6 +272,7 @@ func amiDescriptionAttributes(d *schema.ResourceData, image *ec2.Image, meta int
// Simple attributes first
d.SetId(aws.StringValue(image.ImageId))
d.Set("architecture", image.Architecture)
d.Set("boot_mode", image.BootMode)
d.Set("creation_date", image.CreationDate)
if image.Description != nil {
d.Set("description", image.Description)
Expand Down
105 changes: 105 additions & 0 deletions internal/service/ec2/ami_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ func TestAccEC2AMI_basic(t *testing.T) {
"iops": "0",
"throughput": "0",
"volume_size": "8",
"outpost_arn": "",
"volume_type": "standard",
}),
resource.TestCheckTypeSetElemAttrPair(resourceName, "ebs_block_device.*.snapshot_id", snapshotResourceName, "id"),
Expand Down Expand Up @@ -363,6 +364,66 @@ func TestAccEC2AMI_tags(t *testing.T) {
})
}

func TestAccEC2AMI_outpost(t *testing.T) {
var ami ec2.Image
resourceName := "aws_ami.test"
rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix)

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { acctest.PreCheck(t); acctest.PreCheckOutpostsOutposts(t) },
ErrorCheck: acctest.ErrorCheck(t, ec2.EndpointsID),
Providers: acctest.Providers,
CheckDestroy: testAccCheckAmiDestroy,
Steps: []resource.TestStep{
{
Config: testAccAmiConfigOutpost(rName),
Check: resource.ComposeTestCheckFunc(
testAccCheckAmiExists(resourceName, &ami),
resource.TestCheckTypeSetElemAttrPair(resourceName, "ebs_block_device.*.outpost_arn", " data.aws_outposts_outpost.test", "arn"),
),
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{
"manage_ebs_snapshots",
},
},
},
})
}

func TestAccEC2AMI_boot(t *testing.T) {
var ami ec2.Image
resourceName := "aws_ami.test"
rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix)

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { acctest.PreCheck(t) },
ErrorCheck: acctest.ErrorCheck(t, ec2.EndpointsID),
Providers: acctest.Providers,
CheckDestroy: testAccCheckAmiDestroy,
Steps: []resource.TestStep{
{
Config: testAccAmiConfigBoot(rName),
Check: resource.ComposeTestCheckFunc(
testAccCheckAmiExists(resourceName, &ami),
resource.TestCheckResourceAttr(resourceName, "boot_mode", "uefi"),
),
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{
"manage_ebs_snapshots",
},
},
},
})
}

func testAccCheckAmiDestroy(s *terraform.State) error {
conn := acctest.Provider.Meta().(*conns.AWSClient).EC2Conn

Expand Down Expand Up @@ -597,3 +658,47 @@ resource "aws_ami" "test" {
}
`, rName, tagKey1, tagValue1, tagKey2, tagValue2))
}

func testAccAmiConfigOutpost(rName string) string {
return acctest.ConfigCompose(
testAccAmiConfigBase(rName),
fmt.Sprintf(`
data "aws_outposts_outposts" "test" {}
data "aws_outposts_outpost" "test" {
id = tolist(data.aws_outposts_outposts.test.ids)[0]
}
resource "aws_ami" "test" {
ena_support = true
name = %[1]q
root_device_name = "/dev/sda1"
virtualization_type = "hvm"
ebs_block_device {
device_name = "/dev/sda1"
snapshot_id = aws_ebs_snapshot.test.id
outpost_arn = data.aws_outposts_outpost.test.arn
}
}
`, rName))
}

func testAccAmiConfigBoot(rName string) string {
return acctest.ConfigCompose(
testAccAmiConfigBase(rName),
fmt.Sprintf(`
resource "aws_ami" "test" {
ena_support = true
name = %[1]q
root_device_name = "/dev/sda1"
virtualization_type = "hvm"
boot_mode = "uefi"
ebs_block_device {
device_name = "/dev/sda1"
snapshot_id = aws_ebs_snapshot.test.id
}
}
`, rName))
}
1 change: 1 addition & 0 deletions website/docs/d/ami.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ interpolation.

* `arn` - The ARN of the AMI.
* `architecture` - The OS architecture of the AMI (ie: `i386` or `x86_64`).
* `boot_mode` - The boot mode of the image.
* `block_device_mappings` - Set of objects with block device mappings of the AMI.
* `device_name` - The physical name of the device.
* `ebs` - Map containing EBS information, if the device is EBS based. Unlike most object attributes, these are accessed directly (e.g., `ebs.volume_size` or `ebs["volume_size"]`) rather than accessed through the first element of a list (e.g., `ebs[0].volume_size`).
Expand Down
2 changes: 2 additions & 0 deletions website/docs/r/ami.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ resource "aws_ami" "example" {
The following arguments are supported:

* `name` - (Required) A region-unique name for the AMI.
* `boot_mode` - (Optional) The boot mode of the AMI. For more information, see [Boot modes](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ami-boot.html) in the Amazon Elastic Compute Cloud User Guide.
* `description` - (Optional) A longer, human-readable description for the AMI.
* `ena_support` - (Optional) Specifies whether enhanced networking with ENA is enabled. Defaults to `false`.
* `root_device_name` - (Optional) The name of the root device (for example, `/dev/sda1`, or `/dev/xvda`).
Expand Down Expand Up @@ -87,6 +88,7 @@ Nested `ebs_block_device` blocks have the following structure:
* `kms_key_id` - (Optional) The full ARN of the AWS Key Management Service (AWS KMS) CMK to use when encrypting the snapshots of
an image during a copy operation. This parameter is only required if you want to use a non-default CMK;
if this parameter is not specified, the default CMK for EBS is used
* `outpost_arn` - (Optional) The ARN of the Outpost on which the snapshot is stored.

~> **Note:** You can specify `encrypted` or `snapshot_id` but not both.

Expand Down

0 comments on commit 1cac125

Please sign in to comment.