From 057e773f7d7c587986e50cc5b48ab6ddbf32a208 Mon Sep 17 00:00:00 2001 From: stormcat24 Date: Tue, 25 Apr 2017 01:03:32 +0900 Subject: [PATCH] support task placement policy --- Gopkg.lock | 34 ++++++++--------- cmd/service/init.go | 37 +++++++++++++++++++ service/cluster.go | 76 +++++++++++++++++++------------------- service/types/cluster.go | 28 ++++++++++---- service/types/placement.go | 30 +++++++++++++++ 5 files changed, 143 insertions(+), 62 deletions(-) create mode 100644 service/types/placement.go diff --git a/Gopkg.lock b/Gopkg.lock index 58baf06..f5e138c 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -10,7 +10,7 @@ memo = "537b8d32e8c3e58dec0633a748f5486c3267b4b018a5683e09002c6229ca7dca" branch = "master" name = "github.com/aws/aws-sdk-go" packages = ["aws","aws/awserr","aws/awsutil","aws/client","aws/client/metadata","aws/corehandlers","aws/credentials","aws/credentials/ec2rolecreds","aws/credentials/endpointcreds","aws/credentials/stscreds","aws/defaults","aws/ec2metadata","aws/endpoints","aws/request","aws/session","aws/signer/v4","private/protocol","private/protocol/json/jsonutil","private/protocol/jsonrpc","private/protocol/query","private/protocol/query/queryutil","private/protocol/rest","private/protocol/restxml","private/protocol/xml/xmlutil","service/applicationautoscaling","service/autoscaling","service/ecs","service/elb","service/elbv2","service/s3","service/sts"] - revision = "baba9e786eae5ba978f2007f8e718557b29157c8" + revision = "0e1d7f7c9ff58350ce8f53866ba45487e7153d46" [[projects]] name = "github.com/fatih/color" @@ -19,10 +19,10 @@ memo = "537b8d32e8c3e58dec0633a748f5486c3267b4b018a5683e09002c6229ca7dca" version = "v1.4.1" [[projects]] - branch = "master" name = "github.com/fsnotify/fsnotify" packages = ["."] - revision = "4da3e2cfbabc9f751898f250b49f2439785783a1" + revision = "629574ca2a5df945712d3079857300b5e4da0236" + version = "v1.4.2" [[projects]] name = "github.com/go-ini/ini" @@ -40,7 +40,7 @@ memo = "537b8d32e8c3e58dec0633a748f5486c3267b4b018a5683e09002c6229ca7dca" branch = "master" name = "github.com/hashicorp/hcl" packages = [".","hcl/ast","hcl/parser","hcl/scanner","hcl/strconv","hcl/token","json/parser","json/scanner","json/token"] - revision = "630949a3c5fa3c613328e1b8256052cbc2327c9b" + revision = "7fa7fff964d035e8a162cce3a164b3ad02ad651b" [[projects]] branch = "master" @@ -61,10 +61,10 @@ memo = "537b8d32e8c3e58dec0633a748f5486c3267b4b018a5683e09002c6229ca7dca" version = "v1.1" [[projects]] - branch = "master" name = "github.com/magiconair/properties" packages = ["."] - revision = "51463bfca2576e06c62a8504b5c0f06d61312647" + revision = "f917359f079a3759162704eaa8caeec3d01d9f91" + version = "v1.7.2" [[projects]] name = "github.com/mattn/go-colorable" @@ -88,7 +88,7 @@ memo = "537b8d32e8c3e58dec0633a748f5486c3267b4b018a5683e09002c6229ca7dca" branch = "master" name = "github.com/mitchellh/mapstructure" packages = ["."] - revision = "53818660ed4955e899c0bcafa97299a388bd7c8e" + revision = "cc8532a8e9a55ea36402aa21efdf403a60d34096" [[projects]] name = "github.com/naoina/go-stringutil" @@ -97,16 +97,16 @@ memo = "537b8d32e8c3e58dec0633a748f5486c3267b4b018a5683e09002c6229ca7dca" version = "v0.1.0" [[projects]] - branch = "master" name = "github.com/pelletier/go-buffruneio" packages = ["."] revision = "c37440a7cf42ac63b919c752ca73a85067e05992" + version = "v0.2.0" [[projects]] - branch = "master" name = "github.com/pelletier/go-toml" packages = ["."] - revision = "fe206efb84b2bc8e8cfafe6b4c1826622be969e3" + revision = "13d49d4606eb801b8f01ae542b4afc4c6ee3d84a" + version = "v0.5.0" [[projects]] branch = "master" @@ -121,16 +121,16 @@ memo = "537b8d32e8c3e58dec0633a748f5486c3267b4b018a5683e09002c6229ca7dca" revision = "9be650865eab0c12963d8753212f4f9c66cdcf12" [[projects]] - branch = "master" name = "github.com/spf13/cast" packages = ["."] - revision = "ce135a4ebeee6cfe9a26c93ee0d37825f26113c7" + revision = "acbeb36b902d72a7a4c18e8f3241075e7ab763e4" + version = "v1.1.0" [[projects]] branch = "master" name = "github.com/spf13/cobra" packages = ["."] - revision = "b6cb3958937245a12d4d7728be080a6c758f4136" + revision = "f4f10f6873175e78bb1503da7e78c260a7f3ef63" [[projects]] branch = "master" @@ -142,13 +142,13 @@ memo = "537b8d32e8c3e58dec0633a748f5486c3267b4b018a5683e09002c6229ca7dca" branch = "master" name = "github.com/spf13/pflag" packages = ["."] - revision = "9a906f17374922ed0f74e1b2f593d3723f2ffb00" + revision = "2300d0f8576fe575f71aaa5b9bbe4e1b0dc2eb51" [[projects]] branch = "master" name = "github.com/spf13/viper" packages = ["."] - revision = "84f94806c67f59dd7ae87bc5351f7a9c94a4558d" + revision = "0967fc9aceab2ce9da34061253ac10fb99bba5b2" [[projects]] branch = "master" @@ -160,13 +160,13 @@ memo = "537b8d32e8c3e58dec0633a748f5486c3267b4b018a5683e09002c6229ca7dca" branch = "master" name = "golang.org/x/sys" packages = ["unix"] - revision = "f3918c30c5c2cb527c0b071a27c35120a6c0719a" + revision = "ea9bcade75cb975a0b9738936568ab388b845617" [[projects]] branch = "master" name = "golang.org/x/text" packages = ["internal/gen","internal/triegen","internal/ucd","transform","unicode/cldr","unicode/norm"] - revision = "f4b4367115ec2de254587813edaa901bc1c723a8" + revision = "a9a820217f98f7c8a207ec1e45a874e1fe12c478" [[projects]] name = "gopkg.in/guregu/null.v3" diff --git a/cmd/service/init.go b/cmd/service/init.go index a32d059..d09c873 100644 --- a/cmd/service/init.go +++ b/cmd/service/init.go @@ -153,6 +153,24 @@ func createClusterPlans(srv service.ClusterService) ([]*types.ServiceUpdatePlan, util.PrintlnYellow(" RoleARN = %s", *asg.RoleARN) } + if len(cs.PlacementStrategy) > 0 { + util.PrintlnYellow(" PlacementStrategy:") + } + for _, ps := range cs.PlacementStrategy { + util.PrintlnYellow(" -") + util.PrintlnYellow(" Type = %s", *ps.Type) + util.PrintlnYellow(" Field = %s", *ps.Field) + } + + if len(cs.PlacementConstraints) > 0 { + util.PrintlnYellow(" PlacementConstraints:") + } + for _, pc := range cs.PlacementConstraints { + util.PrintlnYellow(" -") + util.PrintlnYellow(" Type = %s", *pc.Type) + util.PrintlnYellow(" Field = %s", *pc.Expression) + } + util.Println() } @@ -182,6 +200,7 @@ func createClusterPlans(srv service.ClusterService) ([]*types.ServiceUpdatePlan, util.PrintlnYellow(" ContainerName:%v", lb.ContainerName) util.PrintlnYellow(" ContainerPort:%v", lb.ContainerPort) } + if add.AutoScaling != nil && add.AutoScaling.Target != nil { asg := add.AutoScaling.Target util.PrintlnYellow(" AutoScaling:") @@ -189,6 +208,24 @@ func createClusterPlans(srv service.ClusterService) ([]*types.ServiceUpdatePlan, util.PrintlnYellow(" MaxCapacity = %v", asg.MaxCapacity) util.PrintlnYellow(" RoleARN = %s", asg.Role) } + + if len(add.PlacementStrategy) > 0 { + for _, ps := range add.PlacementStrategy { + util.PrintlnYellow(" PlacementStrategy:") + util.PrintlnYellow(" -") + util.PrintlnYellow(" Type = %v", ps.Type) + util.PrintlnYellow(" Field = %v", ps.Field) + } + } + + if len(add.PlacementConstraints) > 0 { + for _, pc := range add.PlacementConstraints { + util.PrintlnYellow(" PlacementConstraints:") + util.PrintlnYellow(" -") + util.PrintlnYellow(" Type = %v", pc.Type) + util.PrintlnYellow(" Expression = %v", pc.Expression) + } + } util.Println() } diff --git a/service/cluster.go b/service/cluster.go index 6f26b54..30f369e 100644 --- a/service/cluster.go +++ b/service/cluster.go @@ -147,56 +147,57 @@ func (s ConcreteClusterService) createServiceUpdatePlan(cluster types.Cluster) ( if len(lciResult.ContainerInstanceArns) == 0 { logger.Main.Warnf("ECS instances not found in cluster '%s' not found", cluster.Name) return nil, nil - } else { - target := output.Clusters[0] + } - if *target.Status != "ACTIVE" { - return nil, fmt.Errorf("Cluster '%s' is not ACTIVE.", cluster.Name) - } + target := output.Clusters[0] + + if *target.Status != "ACTIVE" { + return nil, fmt.Errorf("Cluster '%s' is not ACTIVE.", cluster.Name) + } + + lsResult, err := s.ecsCli.ListServices(cluster.Name) + if err != nil { + return nil, err + } + + currentStacks := map[string]*types.ServiceStack{} + if len(lsResult.ServiceArns) > 0 { - lsResult, err := s.ecsCli.ListServices(cluster.Name) + resDescribeService, err := s.ecsCli.DescribeService(cluster.Name, lsResult.ServiceArns) if err != nil { return nil, err } - currentStacks := map[string]*types.ServiceStack{} - if len(lsResult.ServiceArns) > 0 { + for _, service := range resDescribeService.Services { + if s.targetService == "" || (s.targetService != "" && s.targetService == *service.ServiceName) { - resDescribeService, errds := s.ecsCli.DescribeService(cluster.Name, lsResult.ServiceArns) - if errds != nil { - return nil, errds - } - - for _, service := range resDescribeService.Services { - if s.targetService == "" || (s.targetService != "" && s.targetService == *service.ServiceName) { - autoScaling, err := s.appAutoscalingCli.DescribeScalableTarget(cluster.Name, *service.ServiceName) - if err != nil { - return nil, err - } + autoScaling, err := s.appAutoscalingCli.DescribeScalableTarget(cluster.Name, *service.ServiceName) + if err != nil { + return nil, err + } - currentStacks[*service.ServiceName] = &types.ServiceStack{ - Service: service, - AutoScaling: autoScaling, - } + currentStacks[*service.ServiceName] = &types.ServiceStack{ + Service: service, + AutoScaling: autoScaling, } } } + } - newServices := map[string]*types.Service{} - for name, newService := range cluster.Services { - if s.targetService == "" || (s.targetService != "" && s.targetService == newService.Name) { - s := newService - newServices[name] = &s - } + newServices := map[string]*types.Service{} + for name, newService := range cluster.Services { + if s.targetService == "" || (s.targetService != "" && s.targetService == newService.Name) { + s := newService + newServices[name] = &s } - - return &types.ServiceUpdatePlan{ - Name: cluster.Name, - InstanceARNs: lciResult.ContainerInstanceArns, - CurrentServices: currentStacks, - NewServices: newServices, - }, nil } + + return &types.ServiceUpdatePlan{ + Name: cluster.Name, + InstanceARNs: lciResult.ContainerInstanceArns, + CurrentServices: currentStacks, + NewServices: newServices, + }, nil } func (s ConcreteClusterService) ApplyServicePlans(plans []*types.ServiceUpdatePlan) error { @@ -274,6 +275,8 @@ func (s ConcreteClusterService) ApplyServicePlan(plan *types.ServiceUpdatePlan) MaximumPercent: aws.Int64(add.MaximumPercent.Int64), } } + p.PlacementConstraints = types.ToPlacementConstraints(add.PlacementConstraints) + p.PlacementStrategy = types.ToPlacementStrategy(add.PlacementStrategy) csrv, err := s.ecsCli.CreateService(&p) if err != nil { @@ -540,7 +543,6 @@ func toLoadBalancersNew(values []types.LoadBalancer) []*awsecs.LoadBalancer { loadBalancers = append(loadBalancers, &addElb) } - fmt.Println(loadBalancers) return loadBalancers } diff --git a/service/types/cluster.go b/service/types/cluster.go index 8d9a933..527ae81 100644 --- a/service/types/cluster.go +++ b/service/types/cluster.go @@ -21,14 +21,16 @@ type Cluster struct { type Service struct { Name string - TaskDefinition string `yaml:"task_definition"` - DesiredCount int64 `yaml:"desired_count"` - KeepDesiredCount bool `yaml:"keep_desired_count"` - LoadBalancers []LoadBalancer `yaml:"load_balancers"` - MinimumHealthyPercent null.Int `yaml:"minimum_healthy_percent"` - MaximumPercent null.Int `yaml:"maximum_percent"` - Role string `yaml:"role"` - AutoScaling *AutoScaling `yaml:"autoscaling"` + TaskDefinition string `yaml:"task_definition"` + DesiredCount int64 `yaml:"desired_count"` + KeepDesiredCount bool `yaml:"keep_desired_count"` + LoadBalancers []LoadBalancer `yaml:"load_balancers"` + MinimumHealthyPercent null.Int `yaml:"minimum_healthy_percent"` + MaximumPercent null.Int `yaml:"maximum_percent"` + Role string `yaml:"role"` + AutoScaling *AutoScaling `yaml:"autoscaling"` + PlacementConstraints []PlacementConstraint `yaml:"placement_constraints"` + PlacementStrategy []PlacementStrategy `yaml:"placement_strategy"` } type LoadBalancer struct { @@ -59,3 +61,13 @@ type ServiceScalableTarget struct { MaxCapacity uint `yaml:"max_capacity"` Role string `yaml:"role"` } + +type PlacementConstraint struct { + Expression string `yaml:"expression"` + Type string `yaml:"type"` +} + +type PlacementStrategy struct { + Field string `yaml:"field"` + Type string `yaml:"type"` +} diff --git a/service/types/placement.go b/service/types/placement.go new file mode 100644 index 0000000..334acbd --- /dev/null +++ b/service/types/placement.go @@ -0,0 +1,30 @@ +package types + +import ( + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/ecs" +) + +func ToPlacementConstraints(placementConstraints []PlacementConstraint) []*ecs.PlacementConstraint { + + slice := make([]*ecs.PlacementConstraint, len(placementConstraints)) + for i, pc := range placementConstraints { + slice[i] = &ecs.PlacementConstraint{ + Expression: aws.String(pc.Expression), + Type: aws.String(pc.Type), + } + } + return slice +} + +func ToPlacementStrategy(placementStrategy []PlacementStrategy) []*ecs.PlacementStrategy { + + slice := make([]*ecs.PlacementStrategy, len(placementStrategy)) + for i, pc := range placementStrategy { + slice[i] = &ecs.PlacementStrategy{ + Field: aws.String(pc.Field), + Type: aws.String(pc.Type), + } + } + return slice +}