in substrate/pkg/controller/substrate/cluster/instance.go [34:95]
func (i *Instance) Create(ctx context.Context, substrate *v1alpha1.Substrate) (reconcile.Result, error) {
if len(substrate.Status.PublicSubnetIDs) == 0 || substrate.Status.Cluster.LaunchTemplateVersion == nil {
return reconcile.Result{Requeue: true}, nil
}
instancesOutput, err := i.EC2.DescribeInstancesWithContext(ctx, &ec2.DescribeInstancesInput{Filters: discovery.Filters(substrate)})
if err != nil {
return reconcile.Result{}, fmt.Errorf("describing instances, %w", err)
}
for _, reservation := range instancesOutput.Reservations {
for _, instance := range reservation.Instances {
if aws.StringValue(instance.State.Name) == ec2.InstanceStateNameRunning || aws.StringValue(instance.State.Name) == ec2.InstanceStateNamePending {
for _, tag := range instance.Tags {
if aws.StringValue(tag.Key) == "aws:ec2launchtemplate:version" && aws.StringValue(tag.Value) == aws.StringValue(substrate.Status.Cluster.LaunchTemplateVersion) {
logging.FromContext(ctx).Infof("Found instance %s", aws.StringValue(instance.InstanceId))
return reconcile.Result{}, nil
}
}
}
}
}
overrides := []*ec2.FleetLaunchTemplateOverridesRequest{}
for _, subnet := range substrate.Status.PublicSubnetIDs {
overrides = append(overrides, &ec2.FleetLaunchTemplateOverridesRequest{SubnetId: aws.String(subnet)})
}
createFleetOutput, err := i.EC2.CreateFleetWithContext(ctx, &ec2.CreateFleetInput{
Type: aws.String(ec2.FleetTypeInstant),
LaunchTemplateConfigs: []*ec2.FleetLaunchTemplateConfigRequest{{
Overrides: overrides,
LaunchTemplateSpecification: &ec2.FleetLaunchTemplateSpecificationRequest{
LaunchTemplateName: discovery.Name(substrate),
Version: substrate.Status.Cluster.LaunchTemplateVersion,
}},
},
TargetCapacitySpecification: &ec2.TargetCapacitySpecificationRequest{
DefaultTargetCapacityType: aws.String(ec2.DefaultTargetCapacityTypeOnDemand),
TotalTargetCapacity: aws.Int64(1),
},
TagSpecifications: discovery.Tags(substrate, ec2.ResourceTypeInstance, discovery.Name(substrate)),
OnDemandOptions: &ec2.OnDemandOptionsRequest{AllocationStrategy: aws.String(ec2.FleetOnDemandAllocationStrategyLowestPrice)},
})
if err != nil {
return reconcile.Result{}, fmt.Errorf("creating fleet, %w", err)
}
for _, err := range createFleetOutput.Errors {
if strings.Contains(aws.StringValue(err.ErrorMessage), "Invalid IAM Instance Profile name") {
return reconcile.Result{Requeue: true}, nil
}
return reconcile.Result{}, fmt.Errorf("creating fleet %v", aws.StringValue(err.ErrorMessage))
}
logging.FromContext(ctx).Infof("Created instance %s", aws.StringValue(createFleetOutput.Instances[0].InstanceIds[0]))
if err := i.delete(ctx, substrate, func(instance *ec2.Instance) bool {
if aws.StringValue(instance.InstanceId) == aws.StringValue(createFleetOutput.Instances[0].InstanceIds[0]) {
return false
}
return aws.StringValue(instance.State.Name) == ec2.InstanceStateNameRunning ||
aws.StringValue(instance.State.Name) == ec2.InstanceStateNamePending
}); err != nil {
return reconcile.Result{}, err
}
return reconcile.Result{}, nil
}