diff --git a/pkg/model/awsmodel/spotinst.go b/pkg/model/awsmodel/spotinst.go index 337bcb5e2f..894a28e421 100644 --- a/pkg/model/awsmodel/spotinst.go +++ b/pkg/model/awsmodel/spotinst.go @@ -114,6 +114,10 @@ const ( // instance group to specify the cooldown period (in seconds) for scaling actions. SpotInstanceGroupLabelAutoScalerCooldown = "spotinst.io/autoscaler-cooldown" + // SpotInstanceGroupLabelOtherArchitectureImages Identifier of other architecture image in AWS. + //For each architecture type (amd64, arm64) only one AMI is allowed,first image is from config.InstanceGroup.spec.image + SpotInstanceGroupLabelOtherArchitectureImages = "spotinst.io/other-architecture-images" + // SpotInstanceGroupLabelAutoScalerScaleDown* are the metadata labels used on the // instance group to specify the scale down configuration used by the auto scaler. SpotInstanceGroupLabelAutoScalerScaleDownMaxPercentage = "spotinst.io/autoscaler-scale-down-max-percentage" @@ -533,7 +537,7 @@ func (b *SpotInstanceGroupModelBuilder) buildOcean(c *fi.CloudupModelBuilderCont klog.V(4).Infof("Adding task: Ocean/%s", fi.ValueOf(ocean.Name)) c.AddTask(ocean) - + klog.V(4).Infof("Finish task: Ocean/%s", fi.ValueOf(ocean.Name)) return nil } @@ -567,6 +571,12 @@ func (b *SpotInstanceGroupModelBuilder) buildLaunchSpec(c *fi.CloudupModelBuilde if err != nil { return err } + + case SpotInstanceGroupLabelOtherArchitectureImages: + launchSpec.OtherArchitectureImages, err = parseStringSlice(v) + if err != nil { + return err + } } } diff --git a/upup/pkg/fi/cloudup/spotinsttasks/launch_spec.go b/upup/pkg/fi/cloudup/spotinsttasks/launch_spec.go index 632de37384..58f6e78e21 100644 --- a/upup/pkg/fi/cloudup/spotinsttasks/launch_spec.go +++ b/upup/pkg/fi/cloudup/spotinsttasks/launch_spec.go @@ -55,6 +55,7 @@ type LaunchSpec struct { MinSize *int64 MaxSize *int64 InstanceMetadataOptions *InstanceMetadataOptions + OtherArchitectureImages []string Ocean *Ocean } @@ -157,8 +158,12 @@ func (o *LaunchSpec) Find(c *fi.CloudupContext) (*LaunchSpec, error) { // Image. { + // convert spec from api that reply for multi arch data only in spec.images + if spec.Images != nil && len(spec.Images) > 1 { + spec.SetImageId(fi.PtrTo(fi.ValueOf(spec.Images[0].ImageId))) + actual.OtherArchitectureImages = append(actual.OtherArchitectureImages, fi.ValueOf(spec.Images[1].ImageId)) + } actual.ImageID = spec.ImageID - if o.ImageID != nil && actual.ImageID != nil && fi.ValueOf(actual.ImageID) != fi.ValueOf(o.ImageID) { image, err := resolveImage(cloud, fi.ValueOf(o.ImageID)) @@ -169,6 +174,16 @@ func (o *LaunchSpec) Find(c *fi.CloudupContext) (*LaunchSpec, error) { actual.ImageID = o.ImageID } } + if o.OtherArchitectureImages != nil && actual.OtherArchitectureImages != nil && + (actual.OtherArchitectureImages[0] != o.OtherArchitectureImages[0]) { + image, err := resolveImage(cloud, o.OtherArchitectureImages[0]) + if err != nil { + return nil, err + } + if fi.ValueOf(image.ImageId) == actual.OtherArchitectureImages[0] { + actual.OtherArchitectureImages[0] = o.OtherArchitectureImages[0] + } + } } // User data. @@ -395,12 +410,21 @@ func (_ *LaunchSpec) create(cloud awsup.AWSCloud, a, e, changes *LaunchSpec) err // Image. { - if e.ImageID != nil { + if e.ImageID != nil && len(e.OtherArchitectureImages) == 0 { //old api image, err := resolveImage(cloud, fi.ValueOf(e.ImageID)) if err != nil { return err } spec.SetImageId(image.ImageId) + } else { + if e.ImageID != nil && len(e.OtherArchitectureImages) == 1 { + images, err := buildImages(cloud, e.ImageID, e.OtherArchitectureImages) + if err != nil { + return err + } + spec.SetImageId(nil) + spec.SetImages(images) + } } } @@ -610,7 +634,7 @@ func (_ *LaunchSpec) update(cloud awsup.AWSCloud, a, e, changes *LaunchSpec) err // Image. { - if changes.ImageID != nil { + if changes.ImageID != nil { //old api image, err := resolveImage(cloud, fi.ValueOf(e.ImageID)) if err != nil { return err @@ -619,10 +643,21 @@ func (_ *LaunchSpec) update(cloud awsup.AWSCloud, a, e, changes *LaunchSpec) err if fi.ValueOf(actual.ImageID) != fi.ValueOf(image.ImageId) { spec.SetImageId(image.ImageId) } - changes.ImageID = nil changed = true } + if changes.OtherArchitectureImages != nil { + images, err := buildImages(cloud, spec.ImageID, e.OtherArchitectureImages) + if err != nil { + return err + } + spec.SetImageId(nil) + spec.SetImages(images) + changes.OtherArchitectureImages = nil + changed = true + + } + } // User data. @@ -1139,3 +1174,26 @@ func (o *LaunchSpec) convertBlockDeviceMapping(in *awstasks.BlockDeviceMapping) return out } +func buildImages(cloud awsup.AWSCloud, ImageID *string, OtherArchitectureImages []string) ([]*aws.Images, error) { + var imagesSlice []*aws.Images + var imageIndex = 0 + if ImageID != nil { + image, err := resolveImage(cloud, fi.ValueOf(ImageID)) + if err != nil { + return nil, err + } + imagesSlice = append(imagesSlice, &aws.Images{}) + imagesSlice[imageIndex].SetImageId(image.ImageId) + imageIndex++ + } + if len(OtherArchitectureImages) == 1 { + image2, err := resolveImage(cloud, OtherArchitectureImages[0]) + if err != nil { + return nil, err + } + imagesSlice = append(imagesSlice, &aws.Images{}) + imagesSlice[imageIndex].SetImageId(image2.ImageId) + } + + return imagesSlice, nil +}