amazon-ebs: validate IOPS ratio

This commit is contained in:
Aleksandr Serbin 2020-10-31 13:10:51 +01:00
parent 9ec55d3cd7
commit 0cf9b55c5c
2 changed files with 95 additions and 0 deletions

View File

@ -154,6 +154,11 @@ func (blockDevice BlockDevice) BuildEC2BlockDeviceMapping() *ec2.BlockDeviceMapp
return mapping
}
var iopsRatios = map[string]int64{
"io1": 50,
"io2": 500,
}
func (b *BlockDevice) Prepare(ctx *interpolate.Context) error {
if b.DeviceName == "" {
return fmt.Errorf("The `device_name` must be specified " +
@ -166,6 +171,13 @@ func (b *BlockDevice) Prepare(ctx *interpolate.Context) error {
"true` when setting a kms_key_id.", b.DeviceName)
}
if ratio, ok := iopsRatios[b.VolumeType]; b.VolumeSize != 0 && ok {
if b.IOPS/b.VolumeSize > ratio {
return fmt.Errorf("The maximum ratio of provisioned IOPS to requested volume size "+
"(in GiB) is %v:1 for %s volumes", ratio, b.VolumeType)
}
}
_, err := interpolate.RenderInterface(&b, ctx)
return err
}

View File

@ -7,6 +7,7 @@ import (
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/google/go-cmp/cmp"
"github.com/hashicorp/packer/helper/config"
"github.com/hashicorp/packer/template/interpolate"
)
func TestBlockDevice(t *testing.T) {
@ -182,3 +183,85 @@ func TestBlockDevice(t *testing.T) {
}
}
}
func TestIOPSValidation(t *testing.T) {
cases := []struct {
device BlockDevice
ok bool
msg string
}{
// volume size unknown
{
device: BlockDevice{
DeviceName: "/dev/sdb",
VolumeType: "io1",
IOPS: 1000,
},
ok: true,
},
{
device: BlockDevice{
DeviceName: "/dev/sdb",
VolumeType: "io2",
IOPS: 1000,
},
ok: true,
},
// ratio requirement satisfied
{
device: BlockDevice{
DeviceName: "/dev/sdb",
VolumeType: "io1",
VolumeSize: 50,
IOPS: 1000,
},
ok: true,
},
{
device: BlockDevice{
DeviceName: "/dev/sdb",
VolumeType: "io2",
VolumeSize: 100,
IOPS: 1000,
},
ok: true,
},
// ratio requirement not satisfied
{
device: BlockDevice{
DeviceName: "/dev/sdb",
VolumeType: "io1",
VolumeSize: 10,
IOPS: 2000,
},
ok: false,
msg: "The maximum ratio of provisioned IOPS to requested volume size (in GiB) is 50:1 for io1 volumes",
},
{
device: BlockDevice{
DeviceName: "/dev/sdb",
VolumeType: "io2",
VolumeSize: 50,
IOPS: 30000,
},
ok: false,
msg: "The maximum ratio of provisioned IOPS to requested volume size (in GiB) is 500:1 for io2 volumes",
},
}
ctx := interpolate.Context{}
for _, testCase := range cases {
err := testCase.device.Prepare(&ctx)
if testCase.ok && err != nil {
t.Fatalf("should not error, but: %v", err)
}
if !testCase.ok {
if err == nil {
t.Fatalf("should error")
} else if err.Error() != testCase.msg {
t.Fatalf("wrong error: expected %s, found: %v", testCase.msg, err)
}
}
}
}