Skip to content
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
2 changes: 1 addition & 1 deletion data/data/aws/cluster/master/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ resource "aws_instance" "master" {
root_block_device {
volume_type = var.root_volume_type
volume_size = var.root_volume_size
iops = var.root_volume_type == "io1" ? var.root_volume_iops : 0
iops = var.root_volume_iops
encrypted = var.root_volume_encrypted
kms_key_id = var.root_volume_kms_key_id == "" ? data.aws_ebs_default_kms_key.current.key_arn : var.root_volume_kms_key_id
}
Expand Down
9 changes: 6 additions & 3 deletions data/data/install.openshift.io_installconfigs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,8 @@ spec:
properties:
iops:
description: IOPS defines the amount of provisioned
IOPS. This is only valid for type io1.
IOPS. (KiB/s). IOPS may only be set for io1, io2,
& gp3 volume types.
minimum: 0
type: integer
kmsKeyARN:
Expand Down Expand Up @@ -805,7 +806,8 @@ spec:
properties:
iops:
description: IOPS defines the amount of provisioned IOPS.
This is only valid for type io1.
(KiB/s). IOPS may only be set for io1, io2, & gp3 volume
types.
minimum: 0
type: integer
kmsKeyARN:
Expand Down Expand Up @@ -1606,7 +1608,8 @@ spec:
properties:
iops:
description: IOPS defines the amount of provisioned IOPS.
This is only valid for type io1.
(KiB/s). IOPS may only be set for io1, io2, & gp3 volume
types.
minimum: 0
type: integer
kmsKeyARN:
Expand Down
4 changes: 2 additions & 2 deletions pkg/types/aws/machinepool.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,8 @@ func (a *MachinePool) Set(required *MachinePool) {

// EC2RootVolume defines the storage for an ec2 instance.
type EC2RootVolume struct {
// IOPS defines the amount of provisioned IOPS. This is only valid
// for type io1.
// IOPS defines the amount of provisioned IOPS. (KiB/s). IOPS may only be set for
// io1, io2, & gp3 volume types.
//
// +kubebuilder:validation:Minimum=0
// +optional
Expand Down
44 changes: 39 additions & 5 deletions pkg/types/aws/validation/machinepool.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,9 @@ func ValidateMachinePool(platform *aws.Platform, p *aws.MachinePool, fldPath *fi
}
}

if p.IOPS < 0 {
allErrs = append(allErrs, field.Invalid(fldPath.Child("iops"), p.IOPS, "Storage IOPS must be positive"))
}
if p.Size < 0 {
allErrs = append(allErrs, field.Invalid(fldPath.Child("size"), p.Size, "Storage size must be positive"))
if p.EC2RootVolume.Type != "" {
allErrs = append(allErrs, validateVolumeSize(p, fldPath)...)
allErrs = append(allErrs, validateIOPS(p, fldPath)...)
}

if p.EC2Metadata.Authentication != "" && !validMetadataAuthValues.Has(p.EC2Metadata.Authentication) {
Expand All @@ -52,6 +50,42 @@ func ValidateMachinePool(platform *aws.Platform, p *aws.MachinePool, fldPath *fi
return allErrs
}

func validateVolumeSize(p *aws.MachinePool, fldPath *field.Path) field.ErrorList {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: this function is so small/simple that it could maybe be integrated into the caller if.

allErrs := field.ErrorList{}
volumeSize := p.EC2RootVolume.Size

if volumeSize <= 0 {
allErrs = append(allErrs, field.Invalid(fldPath.Child("size"), volumeSize, "volume size value must be a positive number"))
}

return allErrs
}

func validateIOPS(p *aws.MachinePool, fldPath *field.Path) field.ErrorList {
allErrs := field.ErrorList{}
volumeType := strings.ToLower(p.EC2RootVolume.Type)
iops := p.EC2RootVolume.IOPS

switch volumeType {
case "io1", "io2":
if iops <= 0 {
allErrs = append(allErrs, field.Invalid(fldPath.Child("iops"), iops, "iops must be a positive number"))
}
case "gp3":
if iops < 0 {
allErrs = append(allErrs, field.Invalid(fldPath.Child("iops"), iops, "iops must be a positive number"))
}
case "gp2", "st1", "sc1", "standard":
if iops != 0 {
allErrs = append(allErrs, field.Invalid(fldPath.Child("iops"), iops, fmt.Sprintf("iops not supported for type %s", volumeType)))
}
default:
allErrs = append(allErrs, field.Invalid(fldPath.Child("type"), volumeType, fmt.Sprintf("failed to find volume type %s", volumeType)))
}

return allErrs
}

// ValidateAMIID check the AMI ID is set for a machine pool.
func ValidateAMIID(platform *aws.Platform, p *aws.MachinePool, fldPath *field.Path) field.ErrorList {
allErrs := field.ErrorList{}
Expand Down
78 changes: 61 additions & 17 deletions pkg/types/aws/validation/machinepool_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package validation

import (
"fmt"
"testing"

"github.com/stretchr/testify/assert"
Expand All @@ -21,59 +22,102 @@ func TestValidateMachinePool(t *testing.T) {
pool: &aws.MachinePool{},
},
{
name: "valid zone",
name: "valid zone io instance",
pool: &aws.MachinePool{
Zones: []string{"us-east-1a", "us-east-1b"},
EC2RootVolume: aws.EC2RootVolume{
Type: "io2",
Size: 128,
IOPS: 10000,
},
},
},
{
name: "invalid zone",
name: "valid zone gp3 instance no iops",
pool: &aws.MachinePool{
Zones: []string{"us-east-1a", "us-west-1a"},
Zones: []string{"us-east-1a", "us-east-1b"},
EC2RootVolume: aws.EC2RootVolume{
Type: "gp3",
Size: 128,
},
},
},
{
name: "valid zone gp3 instance with iops",
pool: &aws.MachinePool{
Zones: []string{"us-east-1a", "us-east-1b"},
EC2RootVolume: aws.EC2RootVolume{
Type: "gp3",
Size: 128,
IOPS: 10000,
},
},
expected: `^test-path\.zones\[1]: Invalid value: "us-west-1a": Zone not in configured region \(us-east-1\)$`,
},
{
name: "valid iops",
name: "valid zone gp2 instance no iops",
pool: &aws.MachinePool{
Zones: []string{"us-east-1a", "us-east-1b"},
EC2RootVolume: aws.EC2RootVolume{
IOPS: 10,
Type: "gp2",
Size: 128,
},
},
},
{
name: "invalid iops",
name: "invalid zone gp2 instance with iops",
pool: &aws.MachinePool{
Zones: []string{"us-east-1a", "us-east-1b"},
EC2RootVolume: aws.EC2RootVolume{
IOPS: -10,
Type: "gp2",
Size: 128,
IOPS: 10000,
},
},
expected: `^test-path\.iops: Invalid value: -10: Storage IOPS must be positive$`,
expected: fmt.Sprintf("test-path.iops: Invalid value: 10000: iops not supported for type gp2"),
},
{
name: "valid size",
name: "invalid zone",
pool: &aws.MachinePool{
Zones: []string{"us-east-1a", "us-west-1a"},
EC2RootVolume: aws.EC2RootVolume{
Size: 10,
Type: "io2",
Size: 128,
IOPS: 10000,
},
},
expected: `^test-path\.zones\[1]: Invalid value: "us-west-1a": Zone not in configured region \(us-east-1\)$`,
},
{
name: "invalid size",
name: "invalid volume type",
pool: &aws.MachinePool{
EC2RootVolume: aws.EC2RootVolume{
Size: -10,
Type: "bad-volume-type",
Size: 128,
},
},
expected: `^test-path\.size: Invalid value: -10: Storage size must be positive$`,
expected: fmt.Sprintf("test-path.type: Invalid value: \"bad-volume-type\": failed to find volume type bad-volume-type"),
},
{
name: "valid metadata auth option",
name: "invalid volume size using zero",
pool: &aws.MachinePool{
EC2Metadata: aws.EC2Metadata{
Authentication: "Optional",
EC2RootVolume: aws.EC2RootVolume{
Type: "io2",
Size: 0,
IOPS: 10000,
},
},
expected: fmt.Sprintf("test-path.size: Invalid value: 0: volume size value must be a positive number"),
},
{
name: "invalid volume size using negative",
pool: &aws.MachinePool{
EC2RootVolume: aws.EC2RootVolume{
Type: "gp3",
Size: -1,
IOPS: 10000,
},
},
expected: fmt.Sprintf("test-path.size: Invalid value: -1: volume size value must be a positive number"),
},
{
name: "invalid metadata auth option",
Expand Down
4 changes: 3 additions & 1 deletion pkg/types/aws/validation/platform_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,11 +128,13 @@ func TestValidatePlatform(t *testing.T) {
Region: "us-east-1",
DefaultMachinePlatform: &aws.MachinePool{
EC2RootVolume: aws.EC2RootVolume{
Type: "io1",
IOPS: -10,
Size: 128,
},
},
},
expected: `^test-path\.defaultMachinePlatform\.iops: Invalid value: -10: Storage IOPS must be positive$`,
expected: `^test-path.*iops: Invalid value: -10: iops must be a positive number$`,
},
{
name: "invalid userTags, Name key",
Expand Down
2 changes: 2 additions & 0 deletions pkg/types/validation/machinepools_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@ func TestValidateMachinePool(t *testing.T) {
p.Platform = types.MachinePoolPlatform{
AWS: &aws.MachinePool{
EC2RootVolume: aws.EC2RootVolume{
Type: "io1",
Size: 128,
IOPS: -10,
},
},
Expand Down