func()

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
}