in upup/pkg/fi/cloudup/spotinsttasks/elastigroup.go [795:1352]
func (_ *Elastigroup) update(cloud awsup.AWSCloud, a, e, changes *Elastigroup) error {
klog.V(2).Infof("Updating Elastigroup %q", *e.Name)
actual, err := e.find(cloud.Spotinst().Elastigroup(), *e.Name)
if err != nil {
klog.Errorf("Unable to resolve Elastigroup %q, error: %v", *e.Name, err)
return err
}
var changed bool
group := new(aws.Group)
group.SetId(actual.ID)
// Region.
if changes.Region != nil {
group.SetRegion(e.Region)
changes.Region = nil
changed = true
}
// Strategy.
{
// Spot percentage.
if changes.SpotPercentage != nil {
if group.Strategy == nil {
group.Strategy = new(aws.Strategy)
}
group.Strategy.SetRisk(e.SpotPercentage)
changes.SpotPercentage = nil
changed = true
}
// Orientation.
if changes.Orientation != nil {
if group.Strategy == nil {
group.Strategy = new(aws.Strategy)
}
group.Strategy.SetAvailabilityVsCost(fi.String(string(normalizeOrientation(e.Orientation))))
changes.Orientation = nil
changed = true
}
// Fallback to on-demand.
if changes.FallbackToOnDemand != nil {
if group.Strategy == nil {
group.Strategy = new(aws.Strategy)
}
group.Strategy.SetFallbackToOnDemand(e.FallbackToOnDemand)
changes.FallbackToOnDemand = nil
changed = true
}
// Utilize reserved instances.
if changes.UtilizeReservedInstances != nil {
if group.Strategy == nil {
group.Strategy = new(aws.Strategy)
}
group.Strategy.SetUtilizeReservedInstances(e.UtilizeReservedInstances)
changes.UtilizeReservedInstances = nil
changed = true
}
// Utilize commitments.
if changes.UtilizeCommitments != nil {
if group.Strategy == nil {
group.Strategy = new(aws.Strategy)
}
group.Strategy.SetUtilizeCommitments(e.UtilizeCommitments)
changes.UtilizeCommitments = nil
changed = true
}
// Draining timeout.
if changes.DrainingTimeout != nil {
if group.Strategy == nil {
group.Strategy = new(aws.Strategy)
}
group.Strategy.SetDrainingTimeout(fi.Int(int(*e.DrainingTimeout)))
changes.DrainingTimeout = nil
changed = true
}
}
// Compute.
{
// Product.
if changes.Product != nil {
if group.Compute == nil {
group.Compute = new(aws.Compute)
}
group.Compute.SetProduct(e.Product)
changes.Product = nil
changed = true
}
// On-demand instance type.
{
if changes.OnDemandInstanceType != nil {
if group.Compute == nil {
group.Compute = new(aws.Compute)
}
if group.Compute.InstanceTypes == nil {
group.Compute.InstanceTypes = new(aws.InstanceTypes)
}
group.Compute.InstanceTypes.SetOnDemand(e.OnDemandInstanceType)
changes.OnDemandInstanceType = nil
changed = true
}
}
// Spot instance types.
{
if changes.SpotInstanceTypes != nil {
if group.Compute == nil {
group.Compute = new(aws.Compute)
}
if group.Compute.InstanceTypes == nil {
group.Compute.InstanceTypes = new(aws.InstanceTypes)
}
types := make([]string, len(e.SpotInstanceTypes))
copy(types, e.SpotInstanceTypes)
group.Compute.InstanceTypes.SetSpot(types)
changes.SpotInstanceTypes = nil
changed = true
}
}
// Subnets.
{
if changes.Subnets != nil {
if group.Compute == nil {
group.Compute = new(aws.Compute)
}
subnets := make([]string, len(e.Subnets))
for i, subnet := range e.Subnets {
subnets[i] = fi.StringValue(subnet.ID)
}
group.Compute.SetSubnetIDs(subnets)
changes.Subnets = nil
changed = true
}
}
// Launch specification.
{
// Security groups.
{
if changes.SecurityGroups != nil {
if group.Compute == nil {
group.Compute = new(aws.Compute)
}
if group.Compute.LaunchSpecification == nil {
group.Compute.LaunchSpecification = new(aws.LaunchSpecification)
}
securityGroupIDs := make([]string, len(e.SecurityGroups))
for i, sg := range e.SecurityGroups {
securityGroupIDs[i] = *sg.ID
}
group.Compute.LaunchSpecification.SetSecurityGroupIDs(securityGroupIDs)
changes.SecurityGroups = nil
changed = true
}
}
// User data.
{
if changes.UserData != nil {
userData, err := fi.ResourceAsString(e.UserData)
if err != nil {
return err
}
if len(userData) > 0 {
if group.Compute == nil {
group.Compute = new(aws.Compute)
}
if group.Compute.LaunchSpecification == nil {
group.Compute.LaunchSpecification = new(aws.LaunchSpecification)
}
encoded := base64.StdEncoding.EncodeToString([]byte(userData))
group.Compute.LaunchSpecification.SetUserData(fi.String(encoded))
changed = true
}
changes.UserData = nil
}
}
// Network interfaces.
{
if changes.AssociatePublicIP != nil {
if group.Compute == nil {
group.Compute = new(aws.Compute)
}
if group.Compute.LaunchSpecification == nil {
group.Compute.LaunchSpecification = new(aws.LaunchSpecification)
}
iface := &aws.NetworkInterface{
Description: fi.String("eth0"),
DeviceIndex: fi.Int(0),
DeleteOnTermination: fi.Bool(true),
AssociatePublicIPAddress: changes.AssociatePublicIP,
}
group.Compute.LaunchSpecification.SetNetworkInterfaces([]*aws.NetworkInterface{iface})
changes.AssociatePublicIP = nil
changed = true
}
}
// Root volume options.
{
if opts := changes.RootVolumeOpts; opts != nil {
// Block device mappings.
{
if opts.Type != nil || opts.Size != nil || opts.IOPS != nil {
rootDevice, err := buildRootDevice(cloud, opts, e.ImageID)
if err != nil {
return err
}
mappings := []*aws.BlockDeviceMapping{
e.convertBlockDeviceMapping(rootDevice),
}
ephemeralDevices, err := buildEphemeralDevices(cloud, e.OnDemandInstanceType)
if err != nil {
return err
}
for _, bdm := range ephemeralDevices {
mappings = append(mappings, e.convertBlockDeviceMapping(bdm))
}
if group.Compute == nil {
group.Compute = new(aws.Compute)
}
if group.Compute.LaunchSpecification == nil {
group.Compute.LaunchSpecification = new(aws.LaunchSpecification)
}
group.Compute.LaunchSpecification.SetBlockDeviceMappings(mappings)
changed = true
}
}
// EBS optimization.
{
if opts.Optimization != nil {
if group.Compute == nil {
group.Compute = new(aws.Compute)
}
if group.Compute.LaunchSpecification == nil {
group.Compute.LaunchSpecification = new(aws.LaunchSpecification)
}
group.Compute.LaunchSpecification.SetEBSOptimized(e.RootVolumeOpts.Optimization)
changed = true
}
}
changes.RootVolumeOpts = nil
}
}
// Image.
{
if changes.ImageID != nil {
image, err := resolveImage(cloud, fi.StringValue(e.ImageID))
if err != nil {
return err
}
if *actual.Compute.LaunchSpecification.ImageID != *image.ImageId {
if group.Compute == nil {
group.Compute = new(aws.Compute)
}
if group.Compute.LaunchSpecification == nil {
group.Compute.LaunchSpecification = new(aws.LaunchSpecification)
}
group.Compute.LaunchSpecification.SetImageId(image.ImageId)
changed = true
}
changes.ImageID = nil
}
}
// Tags.
{
if changes.Tags != nil {
if group.Compute == nil {
group.Compute = new(aws.Compute)
}
if group.Compute.LaunchSpecification == nil {
group.Compute.LaunchSpecification = new(aws.LaunchSpecification)
}
group.Compute.LaunchSpecification.SetTags(e.buildTags())
changes.Tags = nil
changed = true
}
}
// IAM instance profile.
{
if changes.IAMInstanceProfile != nil {
if group.Compute == nil {
group.Compute = new(aws.Compute)
}
if group.Compute.LaunchSpecification == nil {
group.Compute.LaunchSpecification = new(aws.LaunchSpecification)
}
iprof := new(aws.IAMInstanceProfile)
iprof.SetName(e.IAMInstanceProfile.GetName())
group.Compute.LaunchSpecification.SetIAMInstanceProfile(iprof)
changes.IAMInstanceProfile = nil
changed = true
}
}
// Monitoring.
{
if changes.Monitoring != nil {
if group.Compute == nil {
group.Compute = new(aws.Compute)
}
if group.Compute.LaunchSpecification == nil {
group.Compute.LaunchSpecification = new(aws.LaunchSpecification)
}
group.Compute.LaunchSpecification.SetMonitoring(e.Monitoring)
changes.Monitoring = nil
changed = true
}
}
// SSH key.
{
if changes.SSHKey != nil {
if group.Compute == nil {
group.Compute = new(aws.Compute)
}
if group.Compute.LaunchSpecification == nil {
group.Compute.LaunchSpecification = new(aws.LaunchSpecification)
}
group.Compute.LaunchSpecification.SetKeyPair(e.SSHKey.Name)
changes.SSHKey = nil
changed = true
}
}
// Load balancers.
{
if len(changes.LoadBalancers) > 0 {
lbs, err := e.buildLoadBalancers(cloud)
if err != nil {
return err
}
if group.Compute == nil {
group.Compute = new(aws.Compute)
}
if group.Compute.LaunchSpecification == nil {
group.Compute.LaunchSpecification = new(aws.LaunchSpecification)
}
if group.Compute.LaunchSpecification.LoadBalancersConfig == nil {
group.Compute.LaunchSpecification.LoadBalancersConfig = new(aws.LoadBalancersConfig)
}
group.Compute.LaunchSpecification.LoadBalancersConfig.LoadBalancers = append(group.Compute.LaunchSpecification.LoadBalancersConfig.LoadBalancers, lbs...)
changes.LoadBalancers = nil
changed = true
}
}
// Target groups.
{
if len(changes.TargetGroups) > 0 {
tgs := e.buildTargetGroups()
if group.Compute == nil {
group.Compute = new(aws.Compute)
}
if group.Compute.LaunchSpecification == nil {
group.Compute.LaunchSpecification = new(aws.LaunchSpecification)
}
if group.Compute.LaunchSpecification.LoadBalancersConfig == nil {
group.Compute.LaunchSpecification.LoadBalancersConfig = new(aws.LoadBalancersConfig)
}
group.Compute.LaunchSpecification.LoadBalancersConfig.LoadBalancers = append(group.Compute.LaunchSpecification.LoadBalancersConfig.LoadBalancers, tgs...)
changes.TargetGroups = nil
changed = true
}
}
// Tenancy.
{
if changes.Tenancy != nil {
if group.Compute == nil {
group.Compute = new(aws.Compute)
}
if group.Compute.LaunchSpecification == nil {
group.Compute.LaunchSpecification = new(aws.LaunchSpecification)
}
group.Compute.LaunchSpecification.SetTenancy(e.Tenancy)
changes.Tenancy = nil
changed = true
}
}
// Health check.
{
if changes.HealthCheckType != nil {
if group.Compute == nil {
group.Compute = new(aws.Compute)
}
if group.Compute.LaunchSpecification == nil {
group.Compute.LaunchSpecification = new(aws.LaunchSpecification)
}
group.Compute.LaunchSpecification.SetHealthCheckType(e.HealthCheckType)
changes.HealthCheckType = nil
changed = true
}
}
}
}
// Capacity.
{
if changes.MinSize != nil {
if group.Capacity == nil {
group.Capacity = new(aws.Capacity)
}
group.Capacity.SetMinimum(fi.Int(int(*e.MinSize)))
changes.MinSize = nil
changed = true
// Scale up the target capacity, if needed.
if int64(*actual.Capacity.Target) < *e.MinSize {
group.Capacity.SetTarget(fi.Int(int(*e.MinSize)))
}
}
if changes.MaxSize != nil {
if group.Capacity == nil {
group.Capacity = new(aws.Capacity)
}
group.Capacity.SetMaximum(fi.Int(int(*e.MaxSize)))
changes.MaxSize = nil
changed = true
}
}
// Auto Scaler.
{
if opts := changes.AutoScalerOpts; opts != nil {
if opts.Enabled != nil {
autoScaler := new(aws.AutoScaleKubernetes)
autoScaler.IsEnabled = e.AutoScalerOpts.Enabled
autoScaler.Cooldown = e.AutoScalerOpts.Cooldown
// Headroom.
if headroom := opts.Headroom; headroom != nil {
autoScaler.IsAutoConfig = fi.Bool(false)
autoScaler.Headroom = &aws.AutoScaleHeadroom{
CPUPerUnit: e.AutoScalerOpts.Headroom.CPUPerUnit,
GPUPerUnit: e.AutoScalerOpts.Headroom.GPUPerUnit,
MemoryPerUnit: e.AutoScalerOpts.Headroom.MemPerUnit,
NumOfUnits: e.AutoScalerOpts.Headroom.NumOfUnits,
}
} else if a.AutoScalerOpts != nil && a.AutoScalerOpts.Headroom != nil {
autoScaler.IsAutoConfig = fi.Bool(true)
autoScaler.SetHeadroom(nil)
}
// Scale down.
if down := opts.Down; down != nil {
autoScaler.Down = &aws.AutoScaleDown{
MaxScaleDownPercentage: down.MaxPercentage,
EvaluationPeriods: down.EvaluationPeriods,
}
} else if a.AutoScalerOpts.Down != nil {
autoScaler.SetDown(nil)
}
// Labels.
if labels := opts.Labels; labels != nil {
autoScaler.Labels = e.buildAutoScaleLabels(e.AutoScalerOpts.Labels)
} else if a.AutoScalerOpts.Labels != nil {
autoScaler.SetLabels(nil)
}
k8s := new(aws.KubernetesIntegration)
k8s.SetAutoScale(autoScaler)
integration := new(aws.Integration)
integration.SetKubernetes(k8s)
group.SetIntegration(integration)
changed = true
}
changes.AutoScalerOpts = nil
}
}
empty := &Elastigroup{}
if !reflect.DeepEqual(empty, changes) {
klog.Warningf("Not all changes applied to Elastigroup %q: %v", *group.ID, changes)
}
if !changed {
klog.V(2).Infof("No changes detected in Elastigroup %q", *group.ID)
return nil
}
klog.V(2).Infof("Updating Elastigroup %q (config: %s)", *group.ID, stringutil.Stringify(group))
// Wrap the raw object as an Elastigroup.
eg, err := spotinst.NewElastigroup(cloud.ProviderID(), group)
if err != nil {
return err
}
// Update the Elastigroup.
if err := cloud.Spotinst().Elastigroup().Update(context.Background(), eg); err != nil {
return fmt.Errorf("spotinst: failed to update elastigroup: %v", err)
}
return nil
}