Skip to content
Closed
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
9 changes: 5 additions & 4 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,14 @@ require (
github.com/DataDog/datadog-api-client-go v1.0.0-beta.16
github.com/Masterminds/sprig/v3 v3.2.2
github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46
github.com/aws/aws-sdk-go-v2 v1.17.7
github.com/aws/aws-sdk-go-v2 v1.23.0
github.com/aws/aws-sdk-go-v2/config v1.18.19
github.com/aws/aws-sdk-go-v2/credentials v1.13.18
github.com/aws/aws-sdk-go-v2/service/ecs v1.24.2
github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2 v1.19.7
github.com/aws/aws-sdk-go-v2/service/lambda v1.30.2
github.com/aws/aws-sdk-go-v2/service/s3 v1.31.0
github.com/aws/aws-sdk-go-v2/service/servicediscovery v1.26.2
github.com/creasty/defaults v1.6.0
github.com/envoyproxy/protoc-gen-validate v0.10.1
github.com/fsouza/fake-gcs-server v1.21.0
Expand Down Expand Up @@ -82,8 +83,8 @@ require (
github.com/apparentlymart/go-textseg v1.0.0 // indirect
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.10 // indirect
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.1 // indirect
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.31 // indirect
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.25 // indirect
github.com/aws/aws-sdk-go-v2/internal/configsources v1.2.3 // indirect
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.5.3 // indirect
github.com/aws/aws-sdk-go-v2/internal/ini v1.3.32 // indirect
github.com/aws/aws-sdk-go-v2/internal/v4a v1.0.23 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.9.11 // indirect
Expand All @@ -93,7 +94,7 @@ require (
github.com/aws/aws-sdk-go-v2/service/sso v1.12.6 // indirect
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.14.6 // indirect
github.com/aws/aws-sdk-go-v2/service/sts v1.18.7 // indirect
github.com/aws/smithy-go v1.13.5 // indirect
github.com/aws/smithy-go v1.17.0 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/cenkalti/backoff/v4 v4.1.3 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
Expand Down
14 changes: 10 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -113,8 +113,9 @@ github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
github.com/aslakhellesoy/gox v1.0.100/go.mod h1:AJl542QsKKG96COVsv0N74HHzVQgDIQPceVUh1aeU2M=
github.com/aws/aws-sdk-go-v2 v1.17.7 h1:CLSjnhJSTSogvqUGhIC6LqFKATMRexcxLZ0i/Nzk9Eg=
github.com/aws/aws-sdk-go-v2 v1.17.7/go.mod h1:uzbQtefpm44goOPmdKyAlXSNcwlRgF3ePWVW6EtJvvw=
github.com/aws/aws-sdk-go-v2 v1.23.0 h1:PiHAzmiQQr6JULBUdvR8fKlA+UPKLT/8KbiqpFBWiAo=
github.com/aws/aws-sdk-go-v2 v1.23.0/go.mod h1:i1XDttT4rnf6vxc9AuskLc6s7XBee8rlLilKlc03uAA=
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.10 h1:dK82zF6kkPeCo8J1e+tGx4JdvDIQzj7ygIoLg8WMuGs=
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.10/go.mod h1:VeTZetY5KRJLuD/7fkQXMU6Mw7H5m/KP2J5Iy9osMno=
github.com/aws/aws-sdk-go-v2/config v1.18.19 h1:AqFK6zFNtq4i1EYu+eC7lcKHYnZagMn6SW171la0bGw=
Expand All @@ -123,10 +124,12 @@ github.com/aws/aws-sdk-go-v2/credentials v1.13.18 h1:EQMdtHwz0ILTW1hoP+EwuWhwCG1
github.com/aws/aws-sdk-go-v2/credentials v1.13.18/go.mod h1:vnwlwjIe+3XJPBYKu1et30ZPABG3VaXJYr8ryohpIyM=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.1 h1:gt57MN3liKiyGopcqgNzJb2+d9MJaKT/q1OksHNXVE4=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.1/go.mod h1:lfUx8puBRdM5lVVMQlwt2v+ofiG/X6Ms+dy0UkG/kXw=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.31 h1:sJLYcS+eZn5EeNINGHSCRAwUJMFVqklwkH36Vbyai7M=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.31/go.mod h1:QT0BqUvX1Bh2ABdTGnjqEjvjzrCfIniM9Sc8zn9Yndo=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.25 h1:1mnRASEKnkqsntcxHaysxwgVoUUp5dkiB+l3llKnqyg=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.2.3 h1:DUwbD79T8gyQ23qVXFUthjzVMTviSHi3y4z58KvghhM=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.2.3/go.mod h1:7sGSz1JCKHWWBHq98m6sMtWQikmYPpxjqOydDemiVoM=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.25/go.mod h1:zBHOPwhBc3FlQjQJE/D3IfPWiWaQmT06Vq9aNukDo0k=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.5.3 h1:AplLJCtIaUZDCbr6+gLYdsYNxne4iuaboJhVt9d+WXI=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.5.3/go.mod h1:ify42Rb7nKeDDPkFjKn7q1bPscVPu/+gmHH8d2c+anU=
github.com/aws/aws-sdk-go-v2/internal/ini v1.3.32 h1:p5luUImdIqywn6JpQsW3tq5GNOxKmOnEpybzPx+d1lk=
github.com/aws/aws-sdk-go-v2/internal/ini v1.3.32/go.mod h1:XGhIBZDEgfqmFIugclZ6FU7v75nHhBDtzuB4xB/tEi4=
github.com/aws/aws-sdk-go-v2/internal/v4a v1.0.23 h1:DWYZIsyqagnWL00f8M/SOr9fN063OEQWn9LLTbdYXsk=
Expand All @@ -147,14 +150,17 @@ github.com/aws/aws-sdk-go-v2/service/lambda v1.30.2 h1:JEUEgBM8HZ27ahhZsIlgfj7xP
github.com/aws/aws-sdk-go-v2/service/lambda v1.30.2/go.mod h1:PmNd6f36wPbp2+B3ZSuvHqqSwggfagEdI18tIb8s91o=
github.com/aws/aws-sdk-go-v2/service/s3 v1.31.0 h1:B1G2pSPvbAtQjilPq+Y7jLIzCOwKzuVEl+aBBaNG0AQ=
github.com/aws/aws-sdk-go-v2/service/s3 v1.31.0/go.mod h1:ncltU6n4Nof5uJttDtcNQ537uNuwYqsZZQcpkd2/GUQ=
github.com/aws/aws-sdk-go-v2/service/servicediscovery v1.26.2 h1:Cq/W87yJuXpGahxRyX+1jo/ChzwI6/fBnC+gE0o2WJk=
github.com/aws/aws-sdk-go-v2/service/servicediscovery v1.26.2/go.mod h1:m8lJjajGWGC1CSllESM3kez9431m+bRpEmkfiyuIsiQ=
github.com/aws/aws-sdk-go-v2/service/sso v1.12.6 h1:5V7DWLBd7wTELVz5bPpwzYy/sikk0gsgZfj40X+l5OI=
github.com/aws/aws-sdk-go-v2/service/sso v1.12.6/go.mod h1:Y1VOmit/Fn6Tz1uFAeCO6Q7M2fmfXSCLeL5INVYsLuY=
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.14.6 h1:B8cauxOH1W1v7rd8RdI/MWnoR4Ze0wIHWrb90qczxj4=
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.14.6/go.mod h1:Lh/bc9XUf8CfOY6Jp5aIkQtN+j1mc+nExc+KXj9jx2s=
github.com/aws/aws-sdk-go-v2/service/sts v1.18.7 h1:bWNgNdRko2x6gqa0blfATqAZKZokPIeM1vfmQt2pnvM=
github.com/aws/aws-sdk-go-v2/service/sts v1.18.7/go.mod h1:JuTnSoeePXmMVe9G8NcjjwgOKEfZ4cOjMuT2IBT/2eI=
github.com/aws/smithy-go v1.13.5 h1:hgz0X/DX0dGqTYpGALqXJoRKRj5oQ7150i5FdTePzO8=
github.com/aws/smithy-go v1.13.5/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA=
github.com/aws/smithy-go v1.17.0 h1:wWJD7LX6PBV6etBUwO0zElG0nWN9rUhp0WdYeHSHAaI=
github.com/aws/smithy-go v1.17.0/go.mod h1:NukqUGpCZIILqqiV0NIjeFh24kd/FAa4beRb6nbIUPE=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
Expand Down
19 changes: 12 additions & 7 deletions pkg/app/piped/executor/ecs/deploy.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ package ecs
import (
"context"

"github.com/aws/aws-sdk-go-v2/service/ecs/types"
"github.com/pipe-cd/pipecd/pkg/app/piped/deploysource"
"github.com/pipe-cd/pipecd/pkg/app/piped/executor"
"github.com/pipe-cd/pipecd/pkg/config"
Expand Down Expand Up @@ -97,9 +98,13 @@ func (e *deployExecutor) ensureSync(ctx context.Context) model.StageStatus {
return model.StageStatus_STAGE_FAILURE
}

primary, _, ok := loadTargetGroups(&e.Input, e.appCfg, e.deploySource)
if !ok {
return model.StageStatus_STAGE_FAILURE
// When the service is not under ELB, target groups are not used.
var primary *types.LoadBalancer = nil
if e.appCfg.Input.IsAccessedViaELB() {
primary, _, ok = loadTargetGroups(&e.Input, e.appCfg, e.deploySource)
if !ok {
return model.StageStatus_STAGE_FAILURE
}
}

recreate := e.appCfg.QuickSync.Recreate
Expand All @@ -115,7 +120,7 @@ func (e *deployExecutor) ensurePrimaryRollout(ctx context.Context) model.StageSt
if !ok {
return model.StageStatus_STAGE_FAILURE
}
servicedefinition, ok := loadServiceDefinition(&e.Input, e.appCfg.Input.ServiceDefinitionFile, e.deploySource)
serviceDefinition, ok := loadServiceDefinition(&e.Input, e.appCfg.Input.ServiceDefinitionFile, e.deploySource)
if !ok {
return model.StageStatus_STAGE_FAILURE
}
Expand All @@ -129,7 +134,7 @@ func (e *deployExecutor) ensurePrimaryRollout(ctx context.Context) model.StageSt
return model.StageStatus_STAGE_FAILURE
}

if !rollout(ctx, &e.Input, e.platformProviderName, e.platformProviderCfg, taskDefinition, servicedefinition, primary) {
if !rollout(ctx, &e.Input, e.platformProviderName, e.platformProviderCfg, taskDefinition, serviceDefinition, primary) {
return model.StageStatus_STAGE_FAILURE
}

Expand All @@ -141,7 +146,7 @@ func (e *deployExecutor) ensureCanaryRollout(ctx context.Context) model.StageSta
if !ok {
return model.StageStatus_STAGE_FAILURE
}
servicedefinition, ok := loadServiceDefinition(&e.Input, e.appCfg.Input.ServiceDefinitionFile, e.deploySource)
serviceDefinition, ok := loadServiceDefinition(&e.Input, e.appCfg.Input.ServiceDefinitionFile, e.deploySource)
if !ok {
return model.StageStatus_STAGE_FAILURE
}
Expand All @@ -155,7 +160,7 @@ func (e *deployExecutor) ensureCanaryRollout(ctx context.Context) model.StageSta
return model.StageStatus_STAGE_FAILURE
}

if !rollout(ctx, &e.Input, e.platformProviderName, e.platformProviderCfg, taskDefinition, servicedefinition, canary) {
if !rollout(ctx, &e.Input, e.platformProviderName, e.platformProviderCfg, taskDefinition, serviceDefinition, canary) {
return model.StageStatus_STAGE_FAILURE
}

Expand Down
88 changes: 88 additions & 0 deletions pkg/app/piped/platformprovider/ecs/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"context"
"errors"
"fmt"
"strings"
"time"

"github.com/aws/aws-sdk-go-v2/aws"
Expand All @@ -27,6 +28,8 @@ import (
"github.com/aws/aws-sdk-go-v2/service/ecs/types"
"github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2"
elbtypes "github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2/types"
"github.com/aws/aws-sdk-go-v2/service/servicediscovery"

"go.uber.org/zap"

"github.com/pipe-cd/pipecd/pkg/app/piped/platformprovider"
Expand All @@ -47,6 +50,7 @@ const (
type client struct {
ecsClient *ecs.Client
elbClient *elasticloadbalancingv2.Client
sdClient *servicediscovery.Client
logger *zap.Logger
}

Expand Down Expand Up @@ -79,6 +83,7 @@ func newClient(region, profile, credentialsFile, roleARN, tokenPath string, logg
}
c.ecsClient = ecs.NewFromConfig(cfg)
c.elbClient = elasticloadbalancingv2.NewFromConfig(cfg)
c.sdClient = servicediscovery.NewFromConfig(cfg)

return c, nil
}
Expand Down Expand Up @@ -481,3 +486,86 @@ func (c *client) TagResource(ctx context.Context, resourceArn string, tags []typ
}
return nil
}

func (c *client) deregisterInstanceFromServiceDiscovery(ctx context.Context, serviceId string, instanceId string) error {
input := &servicediscovery.DeregisterInstanceInput{
ServiceId: aws.String(serviceId),
InstanceId: aws.String(instanceId),
}
_, err := c.sdClient.DeregisterInstance(ctx, input)
if err != nil {
return fmt.Errorf("failed to deregister ECS instance(%s) of service(%s) from Service Discovery: %w", instanceId, serviceId, err)
}
return nil
}

func (c *client) registerInstanceToServiceDiscovery(ctx context.Context, serviceId string, serviceName string, taskArn string) error {
clusterName := clusterName(taskArn)
input1 := &ecs.DescribeTasksInput{
Cluster: aws.String(clusterName),
Tasks: []string{taskArn},
}
output, err := c.ecsClient.DescribeTasks(ctx, input1)
if err != nil || len(output.Tasks) == 0 {
return fmt.Errorf("failed to describe ECS task(%s): %w", taskArn, err)
}

task := output.Tasks[0]
taskId := afterLastSlash(*task.TaskArn)

ipv4, err := ipv4OfTask(task)
if err != nil {
return fmt.Errorf("failed to get privateIPv4Address of task(%s): %w", taskId, err)
}

input := &servicediscovery.RegisterInstanceInput{
ServiceId: aws.String(serviceId),
InstanceId: aws.String(taskId),
Attributes: map[string]string{
"AVAILABILITY_ZONE": *task.AvailabilityZone,
"AWS_INIT_HEALTH_STATUS": "HEALTHY", // the default status in SDK
"AWS_INSTANCE_IPV4": *ipv4,
"ECS_CLUSTER_NAME": clusterName,
"ECS_SERVICE_NAME": serviceName,
"ECS_TASK_DEFINITION_FAMILY": afterLastSlash(*task.TaskDefinitionArn),
"REGION": regionName(taskArn),
},
}

_, err = c.sdClient.RegisterInstance(ctx, input)
if err != nil {
return fmt.Errorf("failed to register ECS instance(%s) of service(%s) to Service Discovery: %w", taskId, serviceId, err)
}
return nil
}

// HACK: it depends on the ARN structure. It may be changed in the future.
func afterLastSlash(str string) string {
strSplit := strings.Split(str, "/")
return strSplit[len(strSplit)-1]
}

// HACK: it depends on the ARN structure. It may be changed in the future.
func clusterName(taskArn string) string {
strSplit := strings.Split(taskArn, "/")
return strSplit[len(strSplit)-2]
}

// HACK: it depends on the ARN structure. It may be changed in the future.
func regionName(taskArn string) string {
return strings.Split(taskArn, "/")[3]
}

// HACK: it depends on the Task's Attatchments and Details structures. It may be changed in the future.
func ipv4OfTask(t types.Task) (*string, error) {
if len(t.Attachments) == 0 {
return nil, fmt.Errorf("failed to get privateIPv4Address of task(%s): the task has no attatchments", *t.TaskArn)
}

for _, detail := range t.Attachments[0].Details {
if *detail.Name == "privateIPv4Address" {
return detail.Value, nil
}
}
return nil, fmt.Errorf("failed to get privateIPv4Address of task(%s): the task has no details of 'privateIPv4Address'", *t.TaskArn)
}
11 changes: 11 additions & 0 deletions pkg/config/application_ecs.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,12 +57,23 @@ type ECSDeploymentInput struct {
// Run standalone task during deployment.
// Default is true.
RunStandaloneTask *bool `json:"runStandaloneTask" default:"true"`
// How the ECS service is accessed.
// Default is ELB.
AccessedVia string `json:"AccessedVia" default:"ELB"`
}

func (in *ECSDeploymentInput) IsStandaloneTask() bool {
return in.ServiceDefinitionFile == ""
}

func (in *ECSDeploymentInput) IsAccessedViaELB() bool {
return in.AccessedVia == "ELB"
}

func (in *ECSDeploymentInput) IsAccessedViaServiceDiscovery() bool {
return in.AccessedVia == "SERVICE_DISCOVERY"
}

type ECSVpcConfiguration struct {
Subnets []string
AssignPublicIP string
Expand Down