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

don't clone original taskdef if no changes are detected #9

Merged
merged 2 commits into from
Nov 6, 2019
Merged
Show file tree
Hide file tree
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
2 changes: 1 addition & 1 deletion asg.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (
"github.com/aws/aws-sdk-go/service/autoscaling/autoscalingiface"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/aws/aws-sdk-go/service/ecs"
"github.com/cenkalti/backoff"
"github.com/cenkalti/backoff/v3"
"log"
"strings"
"sync"
Expand Down
46 changes: 23 additions & 23 deletions asg_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,38 +11,38 @@ type mockAutoScalingClient struct {
}

func (m *mockAutoScalingClient) DescribeAutoScalingGroups(input *autoscaling.DescribeAutoScalingGroupsInput) (*autoscaling.DescribeAutoScalingGroupsOutput, error) {
name := ""
name := ""
return &autoscaling.DescribeAutoScalingGroupsOutput{
AutoScalingGroups: []*autoscaling.Group{
&autoscaling.Group{
Instances: []*autoscaling.Instance{
// TODO
},
LaunchConfigurationName: &name,
},
},
}, nil
AutoScalingGroups: []*autoscaling.Group{
&autoscaling.Group{
Instances: []*autoscaling.Instance{
// TODO
},
LaunchConfigurationName: &name,
},
},
}, nil
}

func TestListASGInstaces(t *testing.T) {
instances, name, err := listASGInstaces(&mockAutoScalingClient{}, "")
if len(instances) != 0 {
t.Errorf("unexpected")
}
if *name != "" {
t.Errorf("unexpected")
}
if err != nil {
t.Errorf("unexpected")
}
if len(instances) != 0 {
t.Errorf("unexpected")
}
if *name != "" {
t.Errorf("unexpected")
}
if err != nil {
t.Errorf("unexpected")
}
}

func TestNeedReplacement(t *testing.T) {
name := ""
name := ""
replace := needReplacement("", autoscaling.Instance{LaunchConfigurationName: &name})
if replace {
t.Errorf("unexpected")
}
if replace {
t.Errorf("unexpected")
}
}

func TestFilterInstancesToReplace(t *testing.T) {
Expand Down
2 changes: 1 addition & 1 deletion cmd/enforce-aws-ecs-asg-launchconfig/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (
"github.com/aws/aws-sdk-go/service/autoscaling"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/aws/aws-sdk-go/service/ecs"
"github.com/cenkalti/backoff"
"github.com/cenkalti/backoff/v3"
"log"
)

Expand Down
2 changes: 1 addition & 1 deletion cmd/update-aws-ecs-service/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/ecs"
"github.com/cenkalti/backoff"
"github.com/cenkalti/backoff/v3"
"log"
"os"
"strings"
Expand Down
5 changes: 3 additions & 2 deletions ecs-alter-service.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@ package awsecs

import (
"errors"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/ecs"
"github.com/cenkalti/backoff"
"github.com/cenkalti/backoff/v3"
"log"
)

Expand All @@ -26,7 +27,7 @@ func alterServiceOrValidatedRollBack(api ecs.ECS, cluster, service string, image
return ErrPermanentNothingToRollback
}
log.Printf("attempt rollback %v", alterSvcErr)
rollback, err := api.UpdateService(&ecs.UpdateServiceInput{Cluster: oldsvc.ClusterArn, Service: oldsvc.ServiceName, TaskDefinition: oldsvc.TaskDefinition, DesiredCount: oldsvc.DesiredCount})
rollback, err := api.UpdateService(&ecs.UpdateServiceInput{Cluster: oldsvc.ClusterArn, Service: oldsvc.ServiceName, TaskDefinition: oldsvc.TaskDefinition, DesiredCount: oldsvc.DesiredCount, ForceNewDeployment: aws.Bool(true)})
if err != nil {
return err
}
Expand Down
118 changes: 87 additions & 31 deletions ecs.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
package awsecs

import (
"encoding/json"
"errors"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/ecs"
"github.com/cenkalti/backoff"
"github.com/cenkalti/backoff/v3"
"log"
"reflect"
)

var (
Expand All @@ -27,56 +29,95 @@ var (
errNoPrimaryDeployment = backoff.Permanent(errors.New("no PRIMARY deployment"))
)

func copy(input ecs.TaskDefinition) ecs.RegisterTaskDefinitionInput {
func copyTd(input ecs.TaskDefinition, tags []*ecs.Tag) ecs.RegisterTaskDefinitionInput {
obj, err := json.Marshal(input)
if err != nil {
panic(err)
}
inputClone := ecs.TaskDefinition{}
err = json.Unmarshal(obj, &inputClone)
if err != nil {
panic(err)
}
output := ecs.RegisterTaskDefinitionInput{}
output.ContainerDefinitions = input.ContainerDefinitions
output.Cpu = input.Cpu
output.ExecutionRoleArn = input.ExecutionRoleArn
output.Family = input.Family
output.IpcMode = input.IpcMode
output.Memory = input.Memory
output.NetworkMode = input.NetworkMode
output.PidMode = input.PidMode
output.PlacementConstraints = input.PlacementConstraints
output.RequiresCompatibilities = input.RequiresCompatibilities
output.TaskRoleArn = input.TaskRoleArn
output.Volumes = input.Volumes
output.ContainerDefinitions = inputClone.ContainerDefinitions
output.Cpu = inputClone.Cpu
output.ExecutionRoleArn = inputClone.ExecutionRoleArn
output.Family = inputClone.Family
// output.InferenceAccelerators // not supported by the current version of the SDK
output.IpcMode = inputClone.IpcMode
output.Memory = inputClone.Memory
output.NetworkMode = inputClone.NetworkMode
output.PidMode = inputClone.PidMode
output.PlacementConstraints = inputClone.PlacementConstraints
output.ProxyConfiguration = inputClone.ProxyConfiguration
output.RequiresCompatibilities = inputClone.RequiresCompatibilities
output.Tags = tags
output.TaskRoleArn = inputClone.TaskRoleArn
output.Volumes = inputClone.Volumes
return output
}

func alterImages(copy ecs.RegisterTaskDefinitionInput, imageMap map[string]string) ecs.RegisterTaskDefinitionInput {
obj, err := json.Marshal(copy)
if err != nil {
panic(err)
}
copyClone := ecs.RegisterTaskDefinitionInput{}
err = json.Unmarshal(obj, &copyClone)
if err != nil {
panic(err)
}
for name, image := range imageMap {
for _, containerDefinition := range copy.ContainerDefinitions {
for _, containerDefinition := range copyClone.ContainerDefinitions {
if *containerDefinition.Name == name {
containerDefinition.Image = aws.String(image)
}
}
}
return copy
return copyClone
}

func alterEnvironments(copy ecs.RegisterTaskDefinitionInput, envMaps map[string]map[string]string) ecs.RegisterTaskDefinitionInput {
obj, err := json.Marshal(copy)
if err != nil {
panic(err)
}
copyClone := ecs.RegisterTaskDefinitionInput{}
err = json.Unmarshal(obj, &copyClone)
if err != nil {
panic(err)
}
for name, envMap := range envMaps {
for i, containerDefinition := range copy.ContainerDefinitions {
for i, containerDefinition := range copyClone.ContainerDefinitions {
if *containerDefinition.Name == name {
new := alterEnvironment(*containerDefinition, envMap)
copy.ContainerDefinitions[i] = &new
altered := alterEnvironment(*containerDefinition, envMap)
copyClone.ContainerDefinitions[i] = &altered
}
}
}
return copy
return copyClone
}

func alterSecrets(copy ecs.RegisterTaskDefinitionInput, secretMaps map[string]map[string]string) ecs.RegisterTaskDefinitionInput {
obj, err := json.Marshal(copy)
if err != nil {
panic(err)
}
copyClone := ecs.RegisterTaskDefinitionInput{}
err = json.Unmarshal(obj, &copyClone)
if err != nil {
panic(err)
}
for name, secretMap := range secretMaps {
for i, containerDefinition := range copy.ContainerDefinitions {
for i, containerDefinition := range copyClone.ContainerDefinitions {
if *containerDefinition.Name == name {
new := alterSecret(*containerDefinition, secretMap)
copy.ContainerDefinitions[i] = &new
altered := alterSecret(*containerDefinition, secretMap)
copyClone.ContainerDefinitions[i] = &altered
}
}
}
return copy
return copyClone
}

func alterEnvironment(copy ecs.ContainerDefinition, envMap map[string]string) ecs.ContainerDefinition {
Expand Down Expand Up @@ -130,13 +171,28 @@ func copyTaskDef(api ecs.ECS, taskdef string, imageMap map[string]string, envMap
if err != nil {
return "", err
}
copy := alterSecrets(alterEnvironments(alterImages(copy(*output.TaskDefinition), imageMap), envMaps), secretMaps)
new, err := api.RegisterTaskDefinition(&copy)
if err != nil {
return "", err

asRegisterTaskDefinitionInput := copyTd(*output.TaskDefinition, output.Tags)
tdCopy := alterSecrets(alterEnvironments(alterImages(asRegisterTaskDefinitionInput, imageMap), envMaps), secretMaps)

// if os.Getenv("DEBUG") == "YES" {
// out, _ := json.Marshal(asRegisterTaskDefinitionInput)
// fmt.Println(string(out))
// out, _ = json.Marshal(tdCopy)
// fmt.Println(string(out))
// panic("something")
// }

if reflect.DeepEqual(asRegisterTaskDefinitionInput, tdCopy) {
return *output.TaskDefinition.TaskDefinitionArn, nil
} else {
tdNew, err := api.RegisterTaskDefinition(&tdCopy)
if err != nil {
return "", err
}
arn := tdNew.TaskDefinition.TaskDefinitionArn
return *arn, nil
}
arn := new.TaskDefinition.TaskDefinitionArn
return *arn, nil
}

func alterService(api ecs.ECS, cluster, service string, imageMap map[string]string, envMaps map[string]map[string]string, secretMaps map[string]map[string]string, desiredCount *int64, taskdef string) (ecs.Service, ecs.Service, error) {
Expand All @@ -156,7 +212,7 @@ func alterService(api ecs.ECS, cluster, service string, imageMap map[string]stri
if desiredCount == nil {
desiredCount = svc.DesiredCount
}
updated, err := api.UpdateService(&ecs.UpdateServiceInput{Cluster: aws.String(cluster), Service: aws.String(service), TaskDefinition: aws.String(newTd), DesiredCount: desiredCount})
updated, err := api.UpdateService(&ecs.UpdateServiceInput{Cluster: aws.String(cluster), Service: aws.String(service), TaskDefinition: aws.String(newTd), DesiredCount: desiredCount, ForceNewDeployment: aws.Bool(true)})
if err != nil {
return *svc, ecs.Service{}, err
}
Expand Down
6 changes: 3 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
module github.com/Autodesk/go-awsecs

go 1.12
go 1.13

require (
github.com/aws/aws-sdk-go v1.19.24
github.com/cenkalti/backoff v0.0.0-20190506075156-2146c9339422
github.com/aws/aws-sdk-go v1.19.49
github.com/cenkalti/backoff/v3 v3.0.0
)
8 changes: 4 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
github.com/aws/aws-sdk-go v1.19.24 h1:qOIYaFxcFg07Vdn799ERpGiuUUIEi5MQ2vYib3CNMp4=
github.com/aws/aws-sdk-go v1.19.24/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
github.com/cenkalti/backoff v0.0.0-20190506075156-2146c9339422 h1:+FKjzBIdfBHYDvxCv+djmDJdes/AoDtg8gpcxowBlF8=
github.com/cenkalti/backoff v0.0.0-20190506075156-2146c9339422/go.mod h1:b6Nc7NRH5C4aCISLry0tLnTjcuTEvoiqcWDdsU0sOGM=
github.com/aws/aws-sdk-go v1.19.49 h1:GUlenK625g5iKrIiRcqRS/CvPMLc8kZRtMxXuXBhFx4=
github.com/aws/aws-sdk-go v1.19.49/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
github.com/cenkalti/backoff/v3 v3.0.0 h1:ske+9nBpD9qZsTBoF41nW5L+AIuFBKMeze18XQ3eG1c=
github.com/cenkalti/backoff/v3 v3.0.0/go.mod h1:cIeZDE3IrqwwJl6VUwCN6trj1oXrTS4rc0ij+ULvLYs=
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af h1:pmfjZENx5imkbgOkpRUYLnmbU7UEFbjtDA2hxJ1ichM=
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=