diff --git a/cli/cage/main.go b/cli/cage/main.go index 07ff4fc..c600972 100644 --- a/cli/cage/main.go +++ b/cli/cage/main.go @@ -20,7 +20,6 @@ func main() { envars := &cage.Envars{ Region: aws.String(""), Cluster: aws.String(""), - LoadBalancerArn: aws.String(""), NextServiceName: aws.String(""), NextServiceDefinitionBase64: aws.String(""), CurrentServiceName: aws.String(""), @@ -47,7 +46,7 @@ func main() { Usage: "generate config file skeleton json", }, cli.BoolFlag{ - Name: "dry-run", + Name: "dryRun", Usage: "describe roll out plan without affecting any resources", }, cli.StringFlag{ @@ -63,12 +62,6 @@ func main() { Usage: "ecs cluster name", Destination: envars.Cluster, }, - cli.StringFlag{ - Name: "loadBalancerArn", - EnvVar: cage.LoadBalancerArnKey, - Usage: "full arn of service load balancer", - Destination: envars.LoadBalancerArn, - }, cli.StringFlag{ Name: "nextServiceName", EnvVar: cage.NextServiceNameKey, @@ -143,7 +136,7 @@ func main() { if err != nil { log.Fatalf(err.Error()) } - if ctx.Bool("dry-run") { + if ctx.Bool("dryRun") { DryRun(envars) } else { if err := Action(envars); err != nil { diff --git a/env.go b/env.go index b57a450..65ff35d 100644 --- a/env.go +++ b/env.go @@ -9,7 +9,6 @@ type Envars struct { _ struct{} `type:"struct"` Region *string `json:"region" type:"string"` Cluster *string `json:"cluster" type:"string" required:"true"` - LoadBalancerArn *string `json:"loadBalancerArn" type:"string" required:"true"` NextServiceName *string `json:"nextServiceName" type:"string" required:"true"` CurrentServiceName *string `json:"currentServiceName" type:"string" required:"true"` NextServiceDefinitionBase64 *string `json:"nextServiceDefinitionBase64" type:"string"` @@ -24,7 +23,6 @@ type Envars struct { const ClusterKey = "CAGE_ECS_CLUSTER" const NextServiceNameKey = "CAGE_NEXT_SERVICE_NAME" const CurrentServiceNameKey = "CAGE_CURRENT_SERVICE_NAME" -const LoadBalancerArnKey = "CAGE_LB_ARN" // either required const NextTaskDefinitionBase64Key = "CAGE_NEXT_TASK_DEFINITION_BASE64" @@ -53,8 +51,6 @@ func EnsureEnvars( // required if isEmpty(dest.Cluster) { return NewErrorf("--cluster [%s] is required", ClusterKey) - } else if isEmpty(dest.LoadBalancerArn) { - return NewErrorf("--loadBalancerArn [%s] is required", LoadBalancerArnKey) } else if isEmpty(dest.CurrentServiceName) { return NewErrorf("--currentServiceName [%s] is required", CurrentServiceNameKey) } else if isEmpty(dest.NextServiceName) { diff --git a/env_test.go b/env_test.go index bff5dc2..ef91ad2 100644 --- a/env_test.go +++ b/env_test.go @@ -17,7 +17,6 @@ func TestEnsureEnvars(t *testing.T) { CurrentServiceName: aws.String("service-current"), NextTaskDefinitionBase64: aws.String("hoge"), NextServiceDefinitionBase64: aws.String("next"), - LoadBalancerArn: aws.String("lb"), AvailabilityThreshold: aws.Float64(0.9), ResponseTimeThreshold: aws.Float64(0.5), RollOutPeriod: aws.Int64(60), @@ -33,7 +32,6 @@ func TestEnsureEnvars4(t *testing.T) { CurrentServiceName: aws.String("service"), NextTaskDefinitionBase64: aws.String("current"), NextServiceName: aws.String("next"), - LoadBalancerArn: aws.String("lb"), } if err := EnsureEnvars(e); err != nil { t.Fatalf(err.Error()) @@ -48,7 +46,6 @@ func TestEnsureEnvars2(t *testing.T) { CurrentServiceNameKey, NextTaskDefinitionBase64Key, ClusterKey, - LoadBalancerArnKey, } for i, v := range arr { m := make(map[string]*string) @@ -56,7 +53,6 @@ func TestEnsureEnvars2(t *testing.T) { m[CurrentServiceNameKey] = dummy m[NextTaskDefinitionBase64Key] = dummy m[ClusterKey] = dummy - m[LoadBalancerArnKey] = dummy for j, u := range arr { if i == j { m[u] = nil @@ -67,7 +63,6 @@ func TestEnsureEnvars2(t *testing.T) { NextServiceName: m[NextServiceNameKey], NextTaskDefinitionBase64: m[NextTaskDefinitionBase64Key], Cluster: m[ClusterKey], - LoadBalancerArn: m[LoadBalancerArnKey], } err := EnsureEnvars(e) if err == nil { @@ -83,7 +78,6 @@ func dummyEnvs() *Envars { NextServiceName: dummy, NextTaskDefinitionBase64: dummy, Cluster: dummy, - LoadBalancerArn: dummy, } } func TestEnsureEnvars3(t *testing.T) { @@ -123,7 +117,6 @@ func TestUnmarshalEnvars(t *testing.T) { } assert.Equal(t, "us-east-2", *dest.Region) assert.Equal(t, "cluster", *dest.Cluster) - assert.Equal(t, "arn://lb", *dest.LoadBalancerArn) assert.Equal(t, "service-next", *dest.NextServiceName) assert.Equal(t, "service-current", *dest.CurrentServiceName) assert.Equal(t, "next-task", *dest.NextTaskDefinitionBase64) diff --git a/metrics.go b/metrics.go index 3d3de69..7ebacbe 100644 --- a/metrics.go +++ b/metrics.go @@ -81,6 +81,7 @@ func (envars *Envars) GetServiceMetricStatistics( func (envars *Envars) AccumulatePeriodicServiceHealth( cw cloudwatchiface.CloudWatchAPI, + loadBalancerArn *string, targetGroupArn *string, startTime time.Time, endTime time.Time, @@ -90,7 +91,7 @@ func (envars *Envars) AccumulatePeriodicServiceHealth( tgId string err error ) - if lbId, err = ExtractAlbId(*envars.LoadBalancerArn); err != nil { + if lbId, err = ExtractAlbId(*loadBalancerArn); err != nil { return nil, err } if tgId, err = ExtractTargetGroupId(*targetGroupArn); err != nil { diff --git a/metrics_test.go b/metrics_test.go index 4336379..276d63c 100644 --- a/metrics_test.go +++ b/metrics_test.go @@ -49,7 +49,6 @@ func TestEnvars_AccumulatePeriodicServiceHealth2(t *testing.T) { defer func() { newTimer = time.NewTimer }() newTimer = fakeTimer envars := &Envars{ - LoadBalancerArn: aws.String("arn://hoge/app/aaa/bbb"), } ctrl := gomock.NewController(t) cw := mock_cloudwatch.NewMockCloudWatchAPI(ctrl) @@ -78,7 +77,7 @@ func TestEnvars_AccumulatePeriodicServiceHealth2(t *testing.T) { }).AnyTimes() // cwがdata pointsを返さなくても指定範囲内でリトライする o, err := envars.AccumulatePeriodicServiceHealth( - cw, aws.String("hoge/targetgroup/aa/bb"), time.Now(), time.Now(), + cw, aws.String("hoge/app/aa/bb"), aws.String("hoge/targetgroup/aa/bb"), time.Now(), time.Now(), ) assert.Nil(t, err) assert.Equal(t, 1.0, o.availability) @@ -86,7 +85,7 @@ func TestEnvars_AccumulatePeriodicServiceHealth2(t *testing.T) { } func TestEnvars_AccumulatePeriodicServiceHealth(t *testing.T) { - envars := &Envars{LoadBalancerArn: aws.String("ff/app/aa/bb")} + envars := &Envars{} ctrl := gomock.NewController(t) cw := mock_cloudwatch.NewMockCloudWatchAPI(ctrl) cw.EXPECT().GetMetricStatistics(gomock.Any()).Return(&cloudwatch.GetMetricStatisticsOutput{ @@ -101,7 +100,7 @@ func TestEnvars_AccumulatePeriodicServiceHealth(t *testing.T) { return fakeTimer(d) } _, err := envars.AccumulatePeriodicServiceHealth( - cw, aws.String("hoge/targetgroup/aa/bb"), time.Now(), time.Now(), + cw, aws.String("hoge/app/aa/bb"), aws.String("hoge/targetgroup/aa/bb"), time.Now(), time.Now(), ) assert.NotNil(t, err) assert.Equal(t, 20, callCnt) diff --git a/rollout.go b/rollout.go index ce12551..da51aca 100644 --- a/rollout.go +++ b/rollout.go @@ -76,6 +76,7 @@ func (envars *Envars) StartGradualRollOut( func (envars *Envars) CanaryTest( cw cloudwatchiface.CloudWatchAPI, + loadBalancerArn *string, targetGroupArn *string, totalRollOutCnt int64, ) error { @@ -92,7 +93,7 @@ func (envars *Envars) CanaryTest( "start accumulating periodic service health of '%s' during %s ~ %s", *envars.NextServiceName, startTime.String(), endTime.String(), ) - health, err := envars.AccumulatePeriodicServiceHealth(cw, targetGroupArn, startTime, endTime) + health, err := envars.AccumulatePeriodicServiceHealth(cw, loadBalancerArn, targetGroupArn, startTime, endTime) if err != nil { return err } @@ -156,7 +157,7 @@ func (envars *Envars) RollOut( return err } // Phase2: service-nextのperiodic healthを計測 - if err := envars.CanaryTest(ctx.Cw, lb.TargetGroupArn, totalRollOutCnt); err != nil { + if err := envars.CanaryTest(ctx.Cw, tg.LoadBalancerArns[0], tg.TargetGroupArn, totalRollOutCnt); err != nil { return err } // Phase3: service-currentからタスクを指定数消す @@ -193,7 +194,7 @@ func (envars *Envars) RollOut( if oldTaskCount == 0 && newTaskCount >= originalDesiredCount { // ロールアウトが終わったら最終検証を行う log.Infof("estimated roll out completed. Do final canary test...") - if err := envars.CanaryTest(ctx.Cw, lb.TargetGroupArn, totalRollOutCnt); err != nil { + if err := envars.CanaryTest(ctx.Cw, tg.LoadBalancerArns[0], tg.TargetGroupArn, totalRollOutCnt); err != nil { log.Errorf("final canary test has failed due to: %s", err) return err } diff --git a/rollout_test.go b/rollout_test.go index 4ac15bb..92bdf72 100644 --- a/rollout_test.go +++ b/rollout_test.go @@ -27,7 +27,6 @@ func DefaultEnvars() *Envars { return &Envars{ Region: aws.String("us-west-2"), RollOutPeriod: aws.Int64(0), - LoadBalancerArn: aws.String("hoge/app/1111/hoge"), Cluster: aws.String("cage-test"), CurrentServiceName: aws.String(kCurrentServiceName), NextServiceName: aws.String(kNextServiceName), diff --git a/test-integration/integration_test.go b/test-integration/integration_test.go index 540a338..5cab10d 100644 --- a/test-integration/integration_test.go +++ b/test-integration/integration_test.go @@ -11,7 +11,6 @@ import ( "github.com/aws/aws-sdk-go/aws/session" "github.com/apex/log" "github.com/aws/aws-sdk-go/service/cloudwatch" - "github.com/aws/aws-sdk-go/service/elbv2/elbv2iface" "github.com/aws/aws-sdk-go/service/elbv2" "net/http" "time" @@ -135,9 +134,16 @@ func setupEnvars() *cage.Envars { return envars } -func GetAlbDNS(alb elbv2iface.ELBV2API, arn *string) (*string, error) { - out, err := alb.DescribeLoadBalancers(&elbv2.DescribeLoadBalancersInput{ - LoadBalancerArns: []*string{arn}, +func GetAlbDNS(ctx *cage.Context, envars *cage.Envars) (*string, error) { + o, _ := ctx.Ecs.DescribeServices(&ecs.DescribeServicesInput{ + Cluster: envars.Cluster, + Services: []*string{envars.CurrentServiceName}, + }) + o2, _ := ctx.Alb.DescribeTargetGroups(&elbv2.DescribeTargetGroupsInput{ + TargetGroupArns: []*string{o.Services[0].LoadBalancers[0].TargetGroupArn}, + }) + out, err := ctx.Alb.DescribeLoadBalancers(&elbv2.DescribeLoadBalancersInput{ + LoadBalancerArns: []*string{o2.TargetGroups[0].LoadBalancerArns[0]}, }) if err != nil { log.Errorf("failed to get alb info due to: %s", err) @@ -149,11 +155,11 @@ func GetAlbDNS(alb elbv2iface.ELBV2API, arn *string) (*string, error) { func PollLoadBalancer( envars *cage.Envars, - alb elbv2iface.ELBV2API, + ctx *cage.Context, interval time.Duration, stop chan bool, ) error { - dns, err := GetAlbDNS(alb, envars.LoadBalancerArn) + dns, err := GetAlbDNS(ctx, envars) if err != nil { log.Errorf(err.Error()) return err @@ -208,7 +214,7 @@ func testInternal(t *testing.T, envars *cage.Envars) (*cage.RollOutResult, error return err }) eg.Go(func() error { - return PollLoadBalancer(envars, ctx.Alb, time.Duration(10)*time.Second, stop) + return PollLoadBalancer(envars, ctx, time.Duration(10)*time.Second, stop) }) return result, eg.Wait() } @@ -274,4 +280,4 @@ func TestHealthyToUnHealthy(t *testing.T) { // 新規サービスのタスクがALBヘルスチェック通らない場合ロールバックされること err := testAbnormal(t, kUnhealthyTDArn, "healthy2unhealthy") assert.Nil(t, err) -} \ No newline at end of file +} diff --git a/test/context.go b/test/context.go index 02cb57b..daaaba0 100644 --- a/test/context.go +++ b/test/context.go @@ -309,8 +309,10 @@ func (ctx *MockContext) DescribeTargetGroups(input *elbv2.DescribeTargetGroupsIn TargetGroups: []*elbv2.TargetGroup{ { TargetGroupName: aws.String("tgname"), + TargetGroupArn: input.TargetGroupArns[0], HealthyThresholdCount: aws.Int64(1), HealthCheckIntervalSeconds: aws.Int64(0), + LoadBalancerArns: []*string { aws.String("arn://hoge/app/aa/bb") }, }, }, }, nil