Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Spotinst: Avoid spurious changes #6028

Merged
merged 3 commits into from
Mar 15, 2019
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
218 changes: 187 additions & 31 deletions upup/pkg/fi/cloudup/spotinsttasks/elastigroup.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ func (e *Elastigroup) Find(c *fi.Context) (*Elastigroup, error) {
actual.Name = group.Name
actual.MinSize = fi.Int64(int64(fi.IntValue(group.Capacity.Minimum)))
actual.MaxSize = fi.Int64(int64(fi.IntValue(group.Capacity.Maximum)))
actual.Risk = group.Strategy.Risk
actual.Orientation = group.Strategy.AvailabilityVsCost

// Compute.
Expand All @@ -134,7 +135,8 @@ func (e *Elastigroup) Find(c *fi.Context) (*Elastigroup, error) {
{
for _, zone := range compute.AvailabilityZones {
if zone.SubnetID != nil {
actual.Subnets = append(actual.Subnets, &awstasks.Subnet{ID: zone.SubnetID})
actual.Subnets = append(actual.Subnets,
&awstasks.Subnet{ID: zone.SubnetID})
}
}
if subnetSlicesEqualIgnoreOrder(actual.Subnets, e.Subnets) {
Expand All @@ -143,53 +145,68 @@ func (e *Elastigroup) Find(c *fi.Context) (*Elastigroup, error) {
}
}

// Launch Specification.
// Launch specification.
{
lc := group.Compute.LaunchSpecification

// Image.
{
image, err := resolveImage(cloud, fi.StringValue(lc.ImageID))
if err != nil {
return nil, err
actual.ImageID = lc.ImageID

if e.ImageID != nil && actual.ImageID != nil &&
fi.StringValue(actual.ImageID) != fi.StringValue(e.ImageID) {
image, err := resolveImage(cloud, fi.StringValue(e.ImageID))
if err != nil {
return nil, err
}
if fi.StringValue(image.ImageId) == fi.StringValue(lc.ImageID) {
actual.ImageID = e.ImageID
}
}
actual.ImageID = image.Name
}

// Tags.
{
if len(lc.Tags) > 0 {
actual.Tags = make(map[string]string)
for _, tag := range lc.Tags {
actual.Tags[*tag.Key] = *tag.Value
actual.Tags[fi.StringValue(tag.Key)] = fi.StringValue(tag.Value)
}
}
}

// Security groups.
{
for _, sg := range lc.SecurityGroupIDs {
actual.SecurityGroups = append(actual.SecurityGroups, &awstasks.SecurityGroup{ID: fi.String(sg)})
for _, sgID := range lc.SecurityGroupIDs {
actual.SecurityGroups = append(actual.SecurityGroups,
&awstasks.SecurityGroup{ID: fi.String(sgID)})
}
}

// Block device mappings.
{
for _, b := range lc.BlockDeviceMappings {
if b.EBS == nil || b.EBS.SnapshotID != nil {
// Not the root.
continue
continue // not the root
}

actual.RootVolumeType = b.EBS.VolumeType
actual.RootVolumeSize = fi.Int64(int64(fi.IntValue(b.EBS.VolumeSize)))
actual.RootVolumeIOPS = fi.Int64(int64(fi.IntValue(b.EBS.IOPS)))
}
}

// EBS optimization.
{
if lc.EBSOptimized != nil {
actual.RootVolumeOptimization = lc.EBSOptimized
}
}

// User data.
{
if lc.UserData != nil {
userData, err := base64.StdEncoding.DecodeString(*lc.UserData)
userData, err := base64.StdEncoding.DecodeString(fi.StringValue(lc.UserData))
if err != nil {
return nil, err
}
Expand All @@ -211,26 +228,74 @@ func (e *Elastigroup) Find(c *fi.Context) (*Elastigroup, error) {
actual.AssociatePublicIP = fi.Bool(associatePublicIP)
}

if lc.LoadBalancersConfig != nil {
if lbs := lc.LoadBalancersConfig.LoadBalancers; len(lbs) > 0 {
actual.LoadBalancer = &awstasks.LoadBalancer{
Name: lbs[0].Name,
LoadBalancerName: lbs[0].Name,
// Load balancer.
{
if lc.LoadBalancersConfig != nil && len(lc.LoadBalancersConfig.LoadBalancers) > 0 {
lbs := lc.LoadBalancersConfig.LoadBalancers
actual.LoadBalancer = &awstasks.LoadBalancer{Name: lbs[0].Name}

if e.LoadBalancer != nil && actual.LoadBalancer != nil &&
fi.StringValue(actual.LoadBalancer.Name) != fi.StringValue(e.LoadBalancer.Name) {
elb, err := awstasks.FindLoadBalancerByNameTag(cloud, fi.StringValue(e.LoadBalancer.Name))
if err != nil {
return nil, err
}
if fi.StringValue(elb.LoadBalancerName) == fi.StringValue(lbs[0].Name) {
actual.LoadBalancer = e.LoadBalancer
}
}
}
}

// IAM instance profile.
if lc.IAMInstanceProfile != nil {
actual.IAMInstanceProfile = &awstasks.IAMInstanceProfile{Name: lc.IAMInstanceProfile.Name}
}

// SSH key.
if lc.KeyPair != nil {
actual.SSHKey = &awstasks.SSHKey{Name: lc.KeyPair}
}

// Tenancy.
if lc.Tenancy != nil {
actual.Tenancy = lc.Tenancy
}

// Monitoring.
if lc.Monitoring != nil {
actual.Monitoring = lc.Monitoring
}
}

// Integration.
{
if group.Integration != nil && group.Integration.Kubernetes != nil {
integration := group.Integration.Kubernetes

// Cluster identifier.
if integration.ClusterIdentifier != nil {
actual.AutoScalerClusterID = integration.ClusterIdentifier
}

// Auto scaler.
if integration.AutoScale != nil {
if integration.AutoScale.IsEnabled != nil {
actual.AutoScalerEnabled = integration.AutoScale.IsEnabled
}

// Labels.
if integration.AutoScale.Labels != nil {
labels := make(map[string]string)
for _, label := range integration.AutoScale.Labels {
labels[fi.StringValue(label.Key)] = fi.StringValue(label.Value)
}
if len(labels) > 0 {
actual.AutoScalerNodeLabels = labels
}
}
}
}
}

// Avoid spurious changes
Expand Down Expand Up @@ -367,7 +432,7 @@ func (_ *Elastigroup) create(cloud awsup.AWSCloud, a, e, changes *Elastigroup) e
}
}

// Image ID.
// Image.
{
image, err := resolveImage(cloud, fi.StringValue(e.ImageID))
if err != nil {
Expand All @@ -378,14 +443,12 @@ func (_ *Elastigroup) create(cloud awsup.AWSCloud, a, e, changes *Elastigroup) e

// User data.
{
if e.UserData != nil {
userData, err := e.UserData.AsString()
if err != nil {
return err
}
encoded := base64.StdEncoding.EncodeToString([]byte(userData))
group.Compute.LaunchSpecification.SetUserData(fi.String(encoded))
userData, err := e.UserData.AsString()
if err != nil {
return err
}
encoded := base64.StdEncoding.EncodeToString([]byte(userData))
group.Compute.LaunchSpecification.SetUserData(fi.String(encoded))
}

// IAM instance profile.
Expand Down Expand Up @@ -531,6 +594,16 @@ func (_ *Elastigroup) update(cloud awsup.AWSCloud, a, e, changes *Elastigroup) e

// Strategy.
{
// Risk.
if changes.Risk != nil {
if group.Strategy == nil {
group.Strategy = new(aws.Strategy)
}

group.Strategy.SetRisk(e.Risk)
changes.Risk = nil
}

// Orientation.
if changes.Orientation != nil {
if group.Strategy == nil {
Expand Down Expand Up @@ -696,7 +769,46 @@ func (_ *Elastigroup) update(cloud awsup.AWSCloud, a, e, changes *Elastigroup) e
}
}

// Image ID.
// Block device mappings.
{
if changes.RootVolumeType != nil || changes.RootVolumeSize != nil || changes.RootVolumeIOPS != nil {
rootDevices, err := e.buildRootDevice(cloud)
if err != nil {
return err
}

ephemeralDevices, err := e.buildEphemeralDevices(e.OnDemandInstanceType)
if err != nil {
return err
}

if len(rootDevices) != 0 || len(ephemeralDevices) != 0 {
var mappings []*aws.BlockDeviceMapping
for device, bdm := range rootDevices {
mappings = append(mappings, e.buildBlockDeviceMapping(device, bdm))
}
for device, bdm := range ephemeralDevices {
mappings = append(mappings, e.buildBlockDeviceMapping(device, bdm))
}
if len(mappings) > 0 {
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)
}
}

changes.RootVolumeType = nil
changes.RootVolumeSize = nil
changes.RootVolumeIOPS = nil
}
}

// Image.
{
if changes.ImageID != nil {
image, err := resolveImage(cloud, fi.StringValue(e.ImageID))
Expand All @@ -711,6 +823,7 @@ func (_ *Elastigroup) update(cloud awsup.AWSCloud, a, e, changes *Elastigroup) e
if group.Compute.LaunchSpecification == nil {
group.Compute.LaunchSpecification = new(aws.LaunchSpecification)
}

group.Compute.LaunchSpecification.SetImageId(image.ImageId)
}

Expand Down Expand Up @@ -753,6 +866,36 @@ func (_ *Elastigroup) update(cloud awsup.AWSCloud, a, e, changes *Elastigroup) e
}
}

// 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
}
}

// EBS optimization.
{
if changes.RootVolumeOptimization != 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.RootVolumeOptimization)
changes.RootVolumeOptimization = nil
}
}

// SSH key.
{
if changes.SSHKey != nil {
Expand Down Expand Up @@ -841,8 +984,21 @@ func (_ *Elastigroup) update(cloud awsup.AWSCloud, a, e, changes *Elastigroup) e
}
}

// Auto Scaler.
// Integration.
{
if changes.AutoScalerClusterID != nil {
if group.Integration == nil {
group.Integration = new(aws.Integration)
}
if group.Integration.Kubernetes == nil {
group.Integration.Kubernetes = new(aws.KubernetesIntegration)
}

group.Integration.Kubernetes.SetClusterIdentifier(e.AutoScalerClusterID)
group.Integration.Kubernetes.SetIntegrationMode(fi.String("pod"))
changes.AutoScalerClusterID = nil
}

if changes.AutoScalerEnabled != nil {
if group.Integration == nil {
group.Integration = new(aws.Integration)
Expand Down Expand Up @@ -1025,7 +1181,7 @@ func (_ *Elastigroup) RenderTerraform(t *terraform.TerraformTarget, a, e, change
}
}

// Security Groups.
// Security groups.
{
for _, sg := range e.SecurityGroups {
tf.SecurityGroups = append(tf.SecurityGroups, sg.TerraformLink())
Expand All @@ -1048,7 +1204,7 @@ func (_ *Elastigroup) RenderTerraform(t *terraform.TerraformTarget, a, e, change
}
}

// IAM Instance Profile.
// IAM instance profile.
{
if e.IAMInstanceProfile != nil {
tf.IAMInstanceProfile = e.IAMInstanceProfile.TerraformLink()
Expand All @@ -1064,7 +1220,7 @@ func (_ *Elastigroup) RenderTerraform(t *terraform.TerraformTarget, a, e, change
}
}

// EBS Optimization.
// EBS optimization.
{
if e.RootVolumeOptimization != nil {
tf.EBSOptimized = e.RootVolumeOptimization
Expand All @@ -1073,7 +1229,7 @@ func (_ *Elastigroup) RenderTerraform(t *terraform.TerraformTarget, a, e, change
}
}

// SSH Key pair.
// SSH key.
{
if e.SSHKey != nil {
tf.KeyName = e.SSHKey.TerraformLink()
Expand Down