mirror of
https://github.com/openshift/installer.git
synced 2026-02-05 06:46:36 +01:00
Merge pull request #10238 from tthvo/CORS-4073
CORS-4073: validate instance type support IPv6 in dual-stack
This commit is contained in:
@@ -4,36 +4,53 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/aws/session"
|
||||
"github.com/aws/aws-sdk-go/service/ec2"
|
||||
"github.com/aws/aws-sdk-go-v2/aws"
|
||||
"github.com/aws/aws-sdk-go-v2/service/ec2"
|
||||
)
|
||||
|
||||
// Networking describes the network settings for an instance type.
|
||||
type Networking struct {
|
||||
// IPv6Supported indicates whether IPv6 is supported.
|
||||
IPv6Supported bool
|
||||
}
|
||||
|
||||
// InstanceType holds metadata for an instance type.
|
||||
type InstanceType struct {
|
||||
DefaultVCpus int64
|
||||
MemInMiB int64
|
||||
Arches []string
|
||||
Networking Networking
|
||||
}
|
||||
|
||||
// instanceTypes retrieves a list of instance types for the given region.
|
||||
func instanceTypes(ctx context.Context, session *session.Session, region string) (map[string]InstanceType, error) {
|
||||
func instanceTypes(ctx context.Context, client *ec2.Client) (map[string]InstanceType, error) {
|
||||
types := map[string]InstanceType{}
|
||||
|
||||
client := ec2.New(session, aws.NewConfig().WithRegion(region))
|
||||
if err := client.DescribeInstanceTypesPagesWithContext(ctx,
|
||||
&ec2.DescribeInstanceTypesInput{},
|
||||
func(page *ec2.DescribeInstanceTypesOutput, lastPage bool) bool {
|
||||
for _, info := range page.InstanceTypes {
|
||||
types[*info.InstanceType] = InstanceType{
|
||||
DefaultVCpus: aws.Int64Value(info.VCpuInfo.DefaultVCpus),
|
||||
MemInMiB: aws.Int64Value(info.MemoryInfo.SizeInMiB),
|
||||
Arches: aws.StringValueSlice(info.ProcessorInfo.SupportedArchitectures),
|
||||
paginator := ec2.NewDescribeInstanceTypesPaginator(client, &ec2.DescribeInstanceTypesInput{})
|
||||
for paginator.HasMorePages() {
|
||||
page, err := paginator.NextPage(ctx)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to list instance types: %w", err)
|
||||
}
|
||||
|
||||
for _, sdkTypeInfo := range page.InstanceTypes {
|
||||
typeInfo := InstanceType{
|
||||
DefaultVCpus: int64(aws.ToInt32(sdkTypeInfo.VCpuInfo.DefaultVCpus)),
|
||||
MemInMiB: aws.ToInt64(sdkTypeInfo.MemoryInfo.SizeInMiB),
|
||||
}
|
||||
|
||||
for _, arch := range sdkTypeInfo.ProcessorInfo.SupportedArchitectures {
|
||||
typeInfo.Arches = append(typeInfo.Arches, string(arch))
|
||||
}
|
||||
|
||||
if netInfo := sdkTypeInfo.NetworkInfo; netInfo != nil {
|
||||
typeInfo.Networking = Networking{
|
||||
IPv6Supported: aws.ToBool(netInfo.Ipv6Supported),
|
||||
}
|
||||
}
|
||||
return !lastPage
|
||||
}); err != nil {
|
||||
return nil, fmt.Errorf("fetching instance types: %w", err)
|
||||
|
||||
types[string(sdkTypeInfo.InstanceType)] = typeInfo
|
||||
}
|
||||
}
|
||||
|
||||
return types, nil
|
||||
|
||||
@@ -377,12 +377,12 @@ func (m *Metadata) InstanceTypes(ctx context.Context) (map[string]InstanceType,
|
||||
defer m.mutex.Unlock()
|
||||
|
||||
if len(m.instanceTypes) == 0 {
|
||||
session, err := m.unlockedSession(ctx)
|
||||
client, err := m.EC2Client(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
m.instanceTypes, err = instanceTypes(ctx, session, m.Region)
|
||||
m.instanceTypes, err = instanceTypes(ctx, client)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error listing instance types: %w", err)
|
||||
}
|
||||
|
||||
@@ -447,6 +447,14 @@ func validateMachinePool(ctx context.Context, meta *Metadata, fldPath *field.Pat
|
||||
errMsg := fmt.Sprintf("instance type supported architectures %s do not match specified architecture %s", sets.List(instanceArches), arch)
|
||||
allErrs = append(allErrs, field.Invalid(fldPath.Child("type"), pool.InstanceType, errMsg))
|
||||
}
|
||||
|
||||
// dual-stack: the instance type must support IPv6 networking
|
||||
if platform.IPFamily.DualStackEnabled() {
|
||||
if !typeMeta.Networking.IPv6Supported {
|
||||
errMsg := fmt.Sprintf("instance type %s does not support IPv6 networking", pool.InstanceType)
|
||||
allErrs = append(allErrs, field.Invalid(fldPath.Child("type"), pool.InstanceType, errMsg))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
errMsg := fmt.Sprintf("instance type %s not found", pool.InstanceType)
|
||||
allErrs = append(allErrs, field.Invalid(fldPath.Child("type"), pool.InstanceType, errMsg))
|
||||
|
||||
@@ -22,6 +22,7 @@ import (
|
||||
"github.com/openshift/installer/pkg/ipnet"
|
||||
"github.com/openshift/installer/pkg/types"
|
||||
"github.com/openshift/installer/pkg/types/aws"
|
||||
"github.com/openshift/installer/pkg/types/network"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -155,6 +156,37 @@ func TestValidate(t *testing.T) {
|
||||
},
|
||||
expectErr: `^compute\[1\].architecture: Invalid value: "arm64": all compute machine pools must be of the same architecture$`,
|
||||
},
|
||||
{
|
||||
name: "valid dual-stack with IPv6 supporting instance types",
|
||||
installConfig: icBuild.build(icBuild.withInstanceType("m5.xlarge", "m5.xlarge", "m5.large"), icBuild.withIPFamily(network.DualStackIPv4Primary)),
|
||||
availRegions: validAvailRegions(),
|
||||
availZones: validAvailZones(),
|
||||
instanceTypes: validInstanceTypes(),
|
||||
},
|
||||
{
|
||||
name: "invalid dual-stack control plane instance type does not support IPv6",
|
||||
installConfig: icBuild.build(icBuild.withInstanceType("m5.xlarge", "m1.xlarge", "m5.large"), icBuild.withIPFamily(network.DualStackIPv4Primary)),
|
||||
availRegions: validAvailRegions(),
|
||||
availZones: validAvailZones(),
|
||||
instanceTypes: validInstanceTypes(),
|
||||
expectErr: `controlPlane\.platform\.aws\.type: Invalid value: "m1\.xlarge": instance type m1\.xlarge does not support IPv6 networking`,
|
||||
},
|
||||
{
|
||||
name: "invalid dual-stack compute instance type does not support IPv6",
|
||||
installConfig: icBuild.build(icBuild.withInstanceType("m5.xlarge", "m5.xlarge", "m1.xlarge"), icBuild.withIPFamily(network.DualStackIPv4Primary)),
|
||||
availRegions: validAvailRegions(),
|
||||
availZones: validAvailZones(),
|
||||
instanceTypes: validInstanceTypes(),
|
||||
expectErr: `compute\[0\]\.platform\.aws\.type: Invalid value: "m1\.xlarge": instance type m1\.xlarge does not support IPv6 networking`,
|
||||
},
|
||||
{
|
||||
name: "invalid dual-stack default machine platform instance types do not support IPv6",
|
||||
installConfig: icBuild.build(icBuild.withInstanceType("m1.xlarge", "", ""), icBuild.withIPFamily(network.DualStackIPv6Primary)),
|
||||
availRegions: validAvailRegions(),
|
||||
availZones: validAvailZones(),
|
||||
instanceTypes: validInstanceTypes(),
|
||||
expectErr: `controlPlane\.platform\.aws\.type: Invalid value: "m1\.xlarge": instance type m1\.xlarge does not support IPv6 networking.*compute\[0\]\.platform\.aws\.type: Invalid value: "m1\.xlarge": instance type m1\.xlarge does not support IPv6 networking`,
|
||||
},
|
||||
{
|
||||
name: "invalid edge pool, missing zones",
|
||||
installConfig: icBuild.build(
|
||||
@@ -1761,21 +1793,41 @@ func validInstanceTypes() map[string]InstanceType {
|
||||
DefaultVCpus: 1,
|
||||
MemInMiB: 2048,
|
||||
Arches: []string{ec2.ArchitectureTypeX8664},
|
||||
Networking: Networking{
|
||||
IPv6Supported: true,
|
||||
},
|
||||
},
|
||||
"m5.large": {
|
||||
DefaultVCpus: 2,
|
||||
MemInMiB: 8192,
|
||||
Arches: []string{ec2.ArchitectureTypeX8664},
|
||||
Networking: Networking{
|
||||
IPv6Supported: true,
|
||||
},
|
||||
},
|
||||
"m5.xlarge": {
|
||||
DefaultVCpus: 4,
|
||||
MemInMiB: 16384,
|
||||
Arches: []string{ec2.ArchitectureTypeX8664},
|
||||
Networking: Networking{
|
||||
IPv6Supported: true,
|
||||
},
|
||||
},
|
||||
"m6g.xlarge": {
|
||||
DefaultVCpus: 4,
|
||||
MemInMiB: 16384,
|
||||
Arches: []string{ec2.ArchitectureTypeArm64},
|
||||
Networking: Networking{
|
||||
IPv6Supported: true,
|
||||
},
|
||||
},
|
||||
"m1.xlarge": {
|
||||
DefaultVCpus: 4,
|
||||
MemInMiB: 15360,
|
||||
Arches: []string{ec2.ArchitectureTypeX8664},
|
||||
Networking: Networking{
|
||||
IPv6Supported: false,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -2025,3 +2077,9 @@ func (icBuild icBuildForAWS) withPublicIPv4Pool(publicIPv4Pool string) icOption
|
||||
ic.Platform.AWS.PublicIpv4Pool = publicIPv4Pool
|
||||
}
|
||||
}
|
||||
|
||||
func (icBuild icBuildForAWS) withIPFamily(ipFamily network.IPFamily) icOption {
|
||||
return func(ic *types.InstallConfig) {
|
||||
ic.Platform.AWS.IPFamily = ipFamily
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user