in pkg/providers/launchtemplate/launchtemplate.go [248:318]
func GetCreateLaunchTemplateInput(
ctx context.Context,
options *amifamily.LaunchTemplate,
ClusterIPFamily corev1.IPFamily,
userData string,
) *ec2.CreateLaunchTemplateInput {
launchTemplateDataTags := []ec2types.LaunchTemplateTagSpecificationRequest{
{ResourceType: ec2types.ResourceTypeNetworkInterface, Tags: utils.EC2MergeTags(options.Tags)},
}
if options.CapacityType == karpv1.CapacityTypeSpot {
launchTemplateDataTags = append(launchTemplateDataTags, ec2types.LaunchTemplateTagSpecificationRequest{ResourceType: ec2types.ResourceTypeSpotInstancesRequest, Tags: utils.EC2MergeTags(options.Tags)})
}
networkInterfaces := generateNetworkInterfaces(options, ClusterIPFamily)
lt := &ec2.CreateLaunchTemplateInput{
LaunchTemplateName: aws.String(LaunchTemplateName(options)),
LaunchTemplateData: &ec2types.RequestLaunchTemplateData{
BlockDeviceMappings: blockDeviceMappings(options.BlockDeviceMappings),
IamInstanceProfile: &ec2types.LaunchTemplateIamInstanceProfileSpecificationRequest{
Name: aws.String(options.InstanceProfile),
},
Monitoring: &ec2types.LaunchTemplatesMonitoringRequest{
Enabled: aws.Bool(options.DetailedMonitoring),
},
// If the network interface is defined, the security groups are defined within it
SecurityGroupIds: lo.Ternary(networkInterfaces != nil, nil, lo.Map(options.SecurityGroups, func(s v1.SecurityGroup, _ int) string { return s.ID })),
UserData: aws.String(userData),
ImageId: aws.String(options.AMIID),
MetadataOptions: &ec2types.LaunchTemplateInstanceMetadataOptionsRequest{
HttpEndpoint: ec2types.LaunchTemplateInstanceMetadataEndpointState(lo.FromPtr(options.MetadataOptions.HTTPEndpoint)),
HttpProtocolIpv6: ec2types.LaunchTemplateInstanceMetadataProtocolIpv6(lo.FromPtr(options.MetadataOptions.HTTPProtocolIPv6)),
//Will be removed when we update options.MetadataOptions.HTTPPutResponseHopLimit type to be int32
//nolint: gosec
HttpPutResponseHopLimit: lo.ToPtr(int32(lo.FromPtr(options.MetadataOptions.HTTPPutResponseHopLimit))),
HttpTokens: ec2types.LaunchTemplateHttpTokensState(lo.FromPtr(options.MetadataOptions.HTTPTokens)),
// We statically set the InstanceMetadataTags to "disabled" for all new instances since
// account-wide defaults can override instance defaults on metadata settings
// This can cause instance failure on accounts that default to instance tags since Karpenter
// can't support instance tags with its current tags (e.g. kubernetes.io/cluster/*, karpenter.k8s.aws/ec2nodeclass)
// See https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-options.html#instance-metadata-options-order-of-precedence
InstanceMetadataTags: ec2types.LaunchTemplateInstanceMetadataTagsStateDisabled,
},
NetworkInterfaces: networkInterfaces,
TagSpecifications: launchTemplateDataTags,
},
TagSpecifications: []ec2types.TagSpecification{
{
ResourceType: ec2types.ResourceTypeLaunchTemplate,
Tags: utils.EC2MergeTags(options.Tags),
},
},
}
// Gate this specifically since the update to CapacityReservationPreference will opt od / spot launches out of open
// ODCRs, which is a breaking change from the pre-native ODCR support behavior.
if karpoptions.FromContext(ctx).FeatureGates.ReservedCapacity {
lt.LaunchTemplateData.CapacityReservationSpecification = &ec2types.LaunchTemplateCapacityReservationSpecificationRequest{
CapacityReservationPreference: lo.Ternary(
options.CapacityType == karpv1.CapacityTypeReserved,
ec2types.CapacityReservationPreferenceCapacityReservationsOnly,
ec2types.CapacityReservationPreferenceNone,
),
CapacityReservationTarget: lo.Ternary(
options.CapacityType == karpv1.CapacityTypeReserved,
&ec2types.CapacityReservationTarget{
CapacityReservationId: &options.CapacityReservationID,
},
nil,
),
}
}
return lt
}