Skip to content
Open
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
132 changes: 1 addition & 131 deletions pkg/asset/cluster/tfvars/tfvars.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ import (
gcpbootstrap "github.com/openshift/installer/pkg/asset/ignition/bootstrap/gcp"
"github.com/openshift/installer/pkg/asset/ignition/machine"
"github.com/openshift/installer/pkg/asset/installconfig"
awsconfig "github.com/openshift/installer/pkg/asset/installconfig/aws"
aztypes "github.com/openshift/installer/pkg/asset/installconfig/azure"
gcpconfig "github.com/openshift/installer/pkg/asset/installconfig/gcp"
ibmcloudconfig "github.com/openshift/installer/pkg/asset/installconfig/ibmcloud"
Expand All @@ -38,7 +37,6 @@ import (
"github.com/openshift/installer/pkg/asset/releaseimage"
"github.com/openshift/installer/pkg/asset/rhcos"
"github.com/openshift/installer/pkg/tfvars"
awstfvars "github.com/openshift/installer/pkg/tfvars/aws"
azuretfvars "github.com/openshift/installer/pkg/tfvars/azure"
baremetaltfvars "github.com/openshift/installer/pkg/tfvars/baremetal"
gcptfvars "github.com/openshift/installer/pkg/tfvars/gcp"
Expand Down Expand Up @@ -222,135 +220,7 @@ func (t *TerraformVariables) Generate(ctx context.Context, parents asset.Parents

switch platform {
case aws.Name:
var vpc string
var privateSubnets []string
var publicSubnets []string

if len(installConfig.Config.Platform.AWS.VPC.Subnets) > 0 {
subnets, err := installConfig.AWS.PrivateSubnets(ctx)
if err != nil {
return err
}

for id := range subnets {
privateSubnets = append(privateSubnets, id)
}

subnets, err = installConfig.AWS.PublicSubnets(ctx)
if err != nil {
return err
}

for id := range subnets {
publicSubnets = append(publicSubnets, id)
}

vpc, err = installConfig.AWS.VPCID(ctx)
if err != nil {
return err
}
}

object := "bootstrap.ign"
bucket := fmt.Sprintf("%s-bootstrap", clusterID.InfraID)

platformAWS := installConfig.Config.Platform.AWS
client, err := awsconfig.NewS3Client(ctx, awsconfig.EndpointOptions{
Region: platformAWS.Region,
Endpoints: platformAWS.ServiceEndpoints,
})
if err != nil {
return fmt.Errorf("failed to create s3 client: %w", err)
}

url, err := awsconfig.PresignedS3URL(ctx, client, bucket, object)
if err != nil {
return err
}
masters, err := mastersAsset.Machines()
if err != nil {
return err
}
masterConfigs := make([]*machinev1beta1.AWSMachineProviderConfig, len(masters))
for i, m := range masters {
masterConfigs[i] = m.Spec.ProviderSpec.Value.Object.(*machinev1beta1.AWSMachineProviderConfig) //nolint:errcheck // legacy, pre-linter
}
workers, err := workersAsset.MachineSets()
if err != nil {
return err
}

workerConfigs := make([]*machinev1beta1.AWSMachineProviderConfig, len(workers))
for i, m := range workers {
workerConfigs[i] = m.Spec.Template.Spec.ProviderSpec.Value.Object.(*machinev1beta1.AWSMachineProviderConfig) //nolint:errcheck // legacy, pre-linter
}
osImage := strings.SplitN(rhcosImage.ControlPlane, ",", 2)
osImageID := osImage[0]
osImageRegion := installConfig.Config.AWS.Region
if len(osImage) == 2 {
osImageRegion = osImage[1]
}

workerIAMRoleName := ""
if mp := installConfig.Config.WorkerMachinePool(); mp != nil {
awsMP := &aws.MachinePool{}
awsMP.Set(installConfig.Config.AWS.DefaultMachinePlatform)
awsMP.Set(mp.Platform.AWS)
workerIAMRoleName = awsMP.IAMRole
}

var securityGroups []string
if mp := installConfig.Config.AWS.DefaultMachinePlatform; mp != nil {
securityGroups = mp.AdditionalSecurityGroupIDs
}
masterIAMRoleName := ""
if mp := installConfig.Config.ControlPlane; mp != nil {
awsMP := &aws.MachinePool{}
awsMP.Set(installConfig.Config.AWS.DefaultMachinePlatform)
awsMP.Set(mp.Platform.AWS)
masterIAMRoleName = awsMP.IAMRole
if len(awsMP.AdditionalSecurityGroupIDs) > 0 {
securityGroups = awsMP.AdditionalSecurityGroupIDs
}
}

// AWS Zones is used to determine which route table the edge zone will be associated.
allZones, err := installConfig.AWS.AllZones(ctx)
if err != nil {
return err
}

data, err := awstfvars.TFVars(awstfvars.TFVarsSources{
VPC: vpc,
PrivateSubnets: privateSubnets,
PublicSubnets: publicSubnets,
AvailabilityZones: allZones,
InternalZone: installConfig.Config.AWS.HostedZone,
InternalZoneRole: installConfig.Config.AWS.HostedZoneRole,
Services: installConfig.Config.AWS.ServiceEndpoints,
Publish: installConfig.Config.Publish,
MasterConfigs: masterConfigs,
WorkerConfigs: workerConfigs,
AMIID: osImageID,
AMIRegion: osImageRegion,
IgnitionBucket: bucket,
IgnitionPresignedURL: url,
AdditionalTrustBundle: installConfig.Config.AdditionalTrustBundle,
MasterIAMRoleName: masterIAMRoleName,
WorkerIAMRoleName: workerIAMRoleName,
Architecture: installConfig.Config.ControlPlane.Architecture,
Proxy: installConfig.Config.Proxy,
PreserveBootstrapIgnition: installConfig.Config.AWS.BestEffortDeleteIgnition,
MasterSecurityGroups: securityGroups,
PublicIpv4Pool: installConfig.Config.AWS.PublicIpv4Pool,
})
if err != nil {
return errors.Wrapf(err, "failed to get %s Terraform variables", platform)
}
t.FileList = append(t.FileList, &asset.File{
Filename: TfPlatformVarsFileName,
Data: data,
})
// AWS uses CAPI for infrastructure provisioning; no Terraform variables needed.
case azure.Name:
session, err := installConfig.Azure.Session()
if err != nil {
Expand Down
2 changes: 1 addition & 1 deletion pkg/asset/installconfig/installconfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ func (a *InstallConfig) finishAWS() error {
if totalEdgeSubnets == 0 {
return nil
}
if edgePool := defaults.CreateEdgeMachinePoolDefaults(a.Config.Compute, &a.Config.Platform, totalEdgeSubnets); edgePool != nil {
if edgePool := defaults.CreateEdgeMachinePoolDefaults(a.Config.Compute, &a.Config.Platform, totalEdgeSubnets, a.Config.EnabledFeatureGates()); edgePool != nil {
a.Config.Compute = append(a.Config.Compute, *edgePool)
}
}
Expand Down
169 changes: 106 additions & 63 deletions pkg/asset/machines/aws/awsmachines.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,97 @@ type MachineInput struct {
Config *types.InstallConfig
}

// CAPIMachineSpecInput defines inputs for building an AWSMachineSpec.
type CAPIMachineSpecInput struct {
InstanceType string
AMI string
IAMInstanceProfile string
Subnet *capa.AWSResourceReference
PublicIP bool
Tags capa.Tags
EC2RootVolume awstypes.EC2RootVolume
KMSKeyARN string
IMDS capa.HTTPTokensState
SecurityGroups []capa.AWSResourceReference
AdditionalSecurityGroupIDs []string
CPUOptions *awstypes.CPUOptions
Ignition *capa.Ignition
DedicatedHostID string
IPFamily network.IPFamily
}

// GenerateCAPIMachineSpec constructs a capa.AWSMachineSpec from the provided inputs.
func GenerateCAPIMachineSpec(in *CAPIMachineSpecInput) capa.AWSMachineSpec {
spec := capa.AWSMachineSpec{
Ignition: in.Ignition,
InstanceType: in.InstanceType,
AMI: capa.AMIReference{ID: ptr.To(in.AMI)},
SSHKeyName: ptr.To(""),
IAMInstanceProfile: in.IAMInstanceProfile,
Subnet: in.Subnet,
PublicIP: ptr.To(in.PublicIP),
AdditionalTags: in.Tags,
RootVolume: &capa.Volume{
Size: int64(in.EC2RootVolume.Size),
Type: capa.VolumeType(in.EC2RootVolume.Type),
IOPS: int64(in.EC2RootVolume.IOPS),
Encrypted: ptr.To(true),
EncryptionKey: in.KMSKeyARN,
},
InstanceMetadataOptions: &capa.InstanceMetadataOptions{
HTTPTokens: in.IMDS,
HTTPEndpoint: capa.InstanceMetadataEndpointStateEnabled,
},
}

if throughput := in.EC2RootVolume.Throughput; throughput != nil {
spec.RootVolume.Throughput = ptr.To(int64(*throughput))
}

spec.AdditionalSecurityGroups = append(spec.AdditionalSecurityGroups, in.SecurityGroups...)
for _, sg := range in.AdditionalSecurityGroupIDs {
spec.AdditionalSecurityGroups = append(
spec.AdditionalSecurityGroups,
capa.AWSResourceReference{ID: ptr.To(sg)},
)
}

if in.CPUOptions != nil {
cpuOptions := capa.CPUOptions{}
if in.CPUOptions.ConfidentialCompute != nil {
cpuOptions.ConfidentialCompute = capa.AWSConfidentialComputePolicy(*in.CPUOptions.ConfidentialCompute)
}
spec.CPUOptions = cpuOptions
}

if in.DedicatedHostID != "" {
spec.Tenancy = "host"
spec.HostAffinity = ptr.To("host")
spec.HostID = ptr.To(in.DedicatedHostID)
}

if in.IPFamily.DualStackEnabled() {
// Only resource-name supports A and AAAA records for private host names
// See: https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/hostname-types.html#ec2-instance-private-hostnames
spec.PrivateDNSName = &capa.PrivateDNSName{
EnableResourceNameDNSAAAARecord: ptr.To(true),
EnableResourceNameDNSARecord: ptr.To(true),
HostnameType: ptr.To("resource-name"),
}
spec.InstanceMetadataOptions.HTTPProtocolIPv6 = capa.InstanceMetadataEndpointStateEnabled

// AssignPrimaryIPv6 is required for IPv6 primary to register instances to IPv6 target groups
switch in.IPFamily {
case network.DualStackIPv6Primary:
spec.AssignPrimaryIPv6 = ptr.To(capa.PrimaryIPv6AssignmentStateEnabled)
case network.DualStackIPv4Primary:
spec.AssignPrimaryIPv6 = ptr.To(capa.PrimaryIPv6AssignmentStateDisabled)
}
}

return spec
}

// GenerateMachines returns manifests and runtime objects to provision the control plane (including bootstrap, if applicable) nodes using CAPI.
func GenerateMachines(clusterID string, in *MachineInput) ([]*asset.RuntimeFile, error) {
if poolPlatform := in.Pool.Platform.Name(); poolPlatform != awstypes.Name {
Expand Down Expand Up @@ -97,55 +188,25 @@ func GenerateMachines(clusterID string, in *MachineInput) ([]*asset.RuntimeFile,
"cluster.x-k8s.io/control-plane": "",
},
},
Spec: capa.AWSMachineSpec{
Ignition: in.Ignition,
UncompressedUserData: ptr.To(true),
InstanceType: mpool.InstanceType,
AMI: capa.AMIReference{ID: ptr.To(mpool.AMIID)},
SSHKeyName: ptr.To(""),
IAMInstanceProfile: instanceProfile,
Subnet: subnet,
PublicIP: ptr.To(in.PublicIP),
AdditionalTags: in.Tags,
RootVolume: &capa.Volume{
Size: int64(mpool.EC2RootVolume.Size),
Type: capa.VolumeType(mpool.EC2RootVolume.Type),
IOPS: int64(mpool.EC2RootVolume.IOPS),
Encrypted: ptr.To(true),
EncryptionKey: mpool.KMSKeyARN,
},
InstanceMetadataOptions: &capa.InstanceMetadataOptions{
HTTPTokens: imds,
HTTPEndpoint: capa.InstanceMetadataEndpointStateEnabled,
},
},
Spec: GenerateCAPIMachineSpec(&CAPIMachineSpecInput{
InstanceType: mpool.InstanceType,
AMI: mpool.AMIID,
IAMInstanceProfile: instanceProfile,
Subnet: subnet,
PublicIP: in.PublicIP,
Tags: in.Tags,
EC2RootVolume: mpool.EC2RootVolume,
KMSKeyARN: mpool.KMSKeyARN,
IMDS: imds,
AdditionalSecurityGroupIDs: mpool.AdditionalSecurityGroupIDs,
CPUOptions: mpool.CPUOptions,
Ignition: in.Ignition,
IPFamily: in.IPFamily,
}),
}
awsMachine.SetGroupVersionKind(capa.GroupVersion.WithKind("AWSMachine"))
utils.SetMachineOSStreamLabels(awsMachine, in.Config)

if throughput := mpool.EC2RootVolume.Throughput; throughput != nil {
awsMachine.Spec.RootVolume.Throughput = ptr.To(int64(*throughput))
}

if in.IPFamily.DualStackEnabled() {
awsMachine.Spec.PrivateDNSName = &capa.PrivateDNSName{
EnableResourceNameDNSAAAARecord: ptr.To(true),
EnableResourceNameDNSARecord: ptr.To(true),
// Only resource-name supports A and AAAA records for private host names
// See: https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/hostname-types.html#ec2-instance-private-hostnames
HostnameType: ptr.To("resource-name"),
}
awsMachine.Spec.InstanceMetadataOptions.HTTPProtocolIPv6 = capa.InstanceMetadataEndpointStateEnabled

// AssignPrimaryIPv6 is required for IPv6 primary to register instances to IPv6 target groups
switch in.IPFamily {
case network.DualStackIPv6Primary:
awsMachine.Spec.AssignPrimaryIPv6 = ptr.To(capa.PrimaryIPv6AssignmentStateEnabled)
case network.DualStackIPv4Primary:
awsMachine.Spec.AssignPrimaryIPv6 = ptr.To(capa.PrimaryIPv6AssignmentStateDisabled)
}
}

if in.Role == "bootstrap" {
awsMachine.Name = capiutils.GenerateBoostrapMachineName(clusterID)
awsMachine.Labels["install.openshift.io/bootstrap"] = ""
Expand All @@ -159,24 +220,6 @@ func GenerateMachines(clusterID string, in *MachineInput) ([]*asset.RuntimeFile,
}
}

// Handle additional security groups.
for _, sg := range mpool.AdditionalSecurityGroupIDs {
awsMachine.Spec.AdditionalSecurityGroups = append(
awsMachine.Spec.AdditionalSecurityGroups,
capa.AWSResourceReference{ID: ptr.To(sg)},
)
}

if mpool.CPUOptions != nil {
cpuOptions := capa.CPUOptions{}

if mpool.CPUOptions.ConfidentialCompute != nil {
cpuOptions.ConfidentialCompute = capa.AWSConfidentialComputePolicy(*mpool.CPUOptions.ConfidentialCompute)
}

awsMachine.Spec.CPUOptions = cpuOptions
}

result = append(result, &asset.RuntimeFile{
File: asset.File{Filename: fmt.Sprintf("10_inframachine_%s.yaml", awsMachine.Name)},
Object: awsMachine,
Expand Down
3 changes: 0 additions & 3 deletions pkg/asset/machines/aws/awsmachines_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,6 @@ func TestGenerateMachines(t *testing.T) {
RootVolume: &capa.Volume{
Encrypted: ptr.To(true),
},
UncompressedUserData: ptr.To(true),
Ignition: &capa.Ignition{
StorageType: capa.IgnitionStorageTypeOptionUnencryptedUserData,
},
Expand Down Expand Up @@ -173,7 +172,6 @@ func TestGenerateMachines(t *testing.T) {
RootVolume: &capa.Volume{
Encrypted: ptr.To(true),
},
UncompressedUserData: ptr.To(true),
Ignition: &capa.Ignition{
StorageType: capa.IgnitionStorageTypeOptionUnencryptedUserData,
},
Expand Down Expand Up @@ -231,7 +229,6 @@ func TestGenerateMachines(t *testing.T) {
RootVolume: &capa.Volume{
Encrypted: ptr.To(true),
},
UncompressedUserData: ptr.To(true),
Ignition: &capa.Ignition{
StorageType: capa.IgnitionStorageTypeOptionUnencryptedUserData,
},
Expand Down
Loading