Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rd/ami - add boot_mode and outpost_arn #22939

Merged
merged 4 commits into from
Feb 4, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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