in pkg/controllers/nodeclass/validation.go [227:281]
func (v *Validation) validateRunInstancesAuthorization(
ctx context.Context,
nodeClass *v1.EC2NodeClass,
nodeClaim *karpv1.NodeClaim,
tags map[string]string,
) (reason string, requeue bool, err error) {
opts, err := v.mockLaunchTemplateOptions(ctx, nodeClaim, nodeClass, tags)
if err != nil {
return "", false, fmt.Errorf("generating options, %w", err)
}
// We can directly marshal from CreateLaunchTemplate LaunchTemplate data
runInstancesInput := &ec2.RunInstancesInput{}
raw, err := json.Marshal(launchtemplate.GetCreateLaunchTemplateInput(ctx, opts, corev1.IPv4Protocol, "").LaunchTemplateData)
if err != nil {
return "", false, fmt.Errorf("converting launch template input to run instances input, %w", err)
}
if err = json.Unmarshal(raw, runInstancesInput); err != nil {
return "", false, fmt.Errorf("converting launch template input to run instances input, %w", err)
}
// Ensure we set specific values for things that are typically overridden in the CreateFleet call
runInstancesInput.DryRun = lo.ToPtr(true)
runInstancesInput.MaxCount = lo.ToPtr[int32](1)
runInstancesInput.MinCount = lo.ToPtr[int32](1)
runInstancesInput.NetworkInterfaces[0].SubnetId = lo.ToPtr(nodeClass.Status.Subnets[0].ID)
runInstancesInput.InstanceType = ec2types.InstanceType(opts.InstanceTypes[0].Name)
runInstancesInput.TagSpecifications = append(runInstancesInput.TagSpecifications,
ec2types.TagSpecification{
ResourceType: ec2types.ResourceTypeInstance,
Tags: runInstancesInput.TagSpecifications[0].Tags,
},
ec2types.TagSpecification{
ResourceType: ec2types.ResourceTypeVolume,
Tags: runInstancesInput.TagSpecifications[0].Tags,
},
)
// Adding NopRetryer to avoid aggressive retry when rate limited
if _, err = v.ec2api.RunInstances(ctx, runInstancesInput, func(o *ec2.Options) {
o.Retryer = aws.NopRetryer{}
}); awserrors.IgnoreDryRunError(err) != nil {
// If we get InstanceProfile NotFound, but we have a resolved instance profile in the status,
// this means there is most likely an eventual consistency issue and we just need to requeue
if awserrors.IsInstanceProfileNotFound(err) || awserrors.IsRateLimitedError(err) {
return "", true, nil
}
if awserrors.IgnoreUnauthorizedOperationError(err) != nil {
// Dry run should only ever return UnauthorizedOperation or DryRunOperation so if we receive any other error
// it would be an unexpected state
return "", false, fmt.Errorf("validating ec2:RunInstances authorization, %w", err)
}
return ConditionReasonRunInstancesAuthFailed, false, nil
}
return "", false, nil
}