Skip to content
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 pkgs/defang/cli.nix
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ buildGo124Module {
pname = "defang-cli";
version = "git";
src = lib.cleanSource ../../src;
vendorHash = "sha256-s7glqopZLTUZIMvYVhyBW9TmnZ8ijL6vMT75CQKzLcc=";
vendorHash = "sha256-qNGoltZteODqZIIWgKwYZrLGTcIIJftkdqj/dRgO1NQ=";

subPackages = [ "cmd/cli" ];

Expand Down
12 changes: 6 additions & 6 deletions src/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -19,20 +19,20 @@ require (
github.com/AlecAivazis/survey/v2 v2.3.7
github.com/DefangLabs/secret-detector v0.0.0-20250811234530-d4b4214cd679
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883
github.com/aws/aws-sdk-go-v2 v1.41.0
github.com/aws/aws-sdk-go-v2 v1.41.4
github.com/aws/aws-sdk-go-v2/config v1.26.6
github.com/aws/aws-sdk-go-v2/service/cloudformation v1.42.6
github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs v1.35.4
github.com/aws/aws-sdk-go-v2/service/codebuild v1.68.12
github.com/aws/aws-sdk-go-v2/service/ec2 v1.145.0
github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.38.7
github.com/aws/aws-sdk-go-v2/service/ecs v1.38.1
github.com/aws/aws-sdk-go-v2/service/route53 v1.37.1
github.com/aws/aws-sdk-go-v2/service/s3 v1.48.1
github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.40.5
github.com/aws/aws-sdk-go-v2/service/servicequotas v1.25.5
github.com/aws/aws-sdk-go-v2/service/ssm v1.44.7
github.com/aws/aws-sdk-go-v2/service/sts v1.26.7
github.com/aws/smithy-go v1.24.0
github.com/aws/smithy-go v1.24.2
github.com/awslabs/goformation/v7 v7.14.9
github.com/compose-spec/compose-go/v2 v2.10.1
github.com/digitalocean/godo v1.131.1
Expand Down Expand Up @@ -67,7 +67,7 @@ require (
google.golang.org/api v0.236.0
google.golang.org/genproto v0.0.0-20250505200425-f936aa4a68b2
google.golang.org/grpc v1.73.0
google.golang.org/protobuf v1.36.9
google.golang.org/protobuf v1.36.11
)

require (
Expand Down Expand Up @@ -149,8 +149,8 @@ require (
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.2 // indirect
github.com/aws/aws-sdk-go-v2/credentials v1.16.16
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.14.11 // indirect
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.16 // indirect
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.16 // indirect
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.20 // indirect
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.20 // indirect
github.com/aws/aws-sdk-go-v2/internal/ini v1.7.3 // indirect
github.com/aws/aws-sdk-go-v2/internal/v4a v1.2.10 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.10.4 // indirect
Expand Down
24 changes: 12 additions & 12 deletions src/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,8 @@ github.com/agext/levenshtein v1.2.3 h1:YB2fHEn0UJagG8T1rrWknE3ZQzWM06O8AMAatNn7l
github.com/agext/levenshtein v1.2.3/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558=
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883 h1:bvNMNQO63//z+xNgfBlViaCIJKLlCJ6/fmUseuG0wVQ=
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8=
github.com/aws/aws-sdk-go-v2 v1.41.0 h1:tNvqh1s+v0vFYdA1xq0aOJH+Y5cRyZ5upu6roPgPKd4=
github.com/aws/aws-sdk-go-v2 v1.41.0/go.mod h1:MayyLB8y+buD9hZqkCW3kX1AKq07Y5pXxtgB+rRFhz0=
github.com/aws/aws-sdk-go-v2 v1.41.4 h1:10f50G7WyU02T56ox1wWXq+zTX9I1zxG46HYuG1hH/k=
github.com/aws/aws-sdk-go-v2 v1.41.4/go.mod h1:mwsPRE8ceUUpiTgF7QmQIJ7lgsKUPQOUl3o72QBrE1o=
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.2 h1:x6xsQXGSmW6frevwDA+vi/wqhp1ct18mVXYN08/93to=
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.2/go.mod h1:lPprDr1e6cJdyYeGXnRaJoP4Md+cDBvi2eOj00BlGmg=
github.com/aws/aws-sdk-go-v2/config v1.26.6 h1:Z/7w9bUqlRI0FFQpetVuFYEsjzE3h7fpU6HuGmfPL/o=
Expand All @@ -62,10 +62,10 @@ github.com/aws/aws-sdk-go-v2/credentials v1.16.16 h1:8q6Rliyv0aUFAVtzaldUEcS+T5g
github.com/aws/aws-sdk-go-v2/credentials v1.16.16/go.mod h1:UHVZrdUsv63hPXFo1H7c5fEneoVo9UXiz36QG1GEPi0=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.14.11 h1:c5I5iH+DZcH3xOIMlz3/tCKJDaHFwYEmxvlh2fAcFo8=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.14.11/go.mod h1:cRrYDYAMUohBJUtUnOhydaMHtiK/1NZ0Otc9lIb6O0Y=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.16 h1:rgGwPzb82iBYSvHMHXc8h9mRoOUBZIGFgKb9qniaZZc=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.16/go.mod h1:L/UxsGeKpGoIj6DxfhOWHWQ/kGKcd4I1VncE4++IyKA=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.16 h1:1jtGzuV7c82xnqOVfx2F0xmJcOw5374L7N6juGW6x6U=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.16/go.mod h1:M2E5OQf+XLe+SZGmmpaI2yy+J326aFf6/+54PoxSANc=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.20 h1:CNXO7mvgThFGqOFgbNAP2nol2qAWBOGfqR/7tQlvLmc=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.20/go.mod h1:oydPDJKcfMhgfcgBUZaG+toBbwy8yPWubJXBVERtI4o=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.20 h1:tN6W/hg+pkM+tf9XDkWUbDEjGLb+raoBMFsTodcoYKw=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.20/go.mod h1:YJ898MhD067hSHA6xYCx5ts/jEd8BSOLtQDL3iZsvbc=
github.com/aws/aws-sdk-go-v2/internal/ini v1.7.3 h1:n3GDfwqF2tzEkXlv5cuy4iy7LpKDtqDMcNLfZDu9rls=
github.com/aws/aws-sdk-go-v2/internal/ini v1.7.3/go.mod h1:6fQQgfuGmw8Al/3M2IgIllycxV7ZW7WCdVSqfBeUiCY=
github.com/aws/aws-sdk-go-v2/internal/v4a v1.2.10 h1:5oE2WzJE56/mVveuDZPJESKlg/00AaS2pY2QZcnxg4M=
Expand All @@ -74,12 +74,12 @@ github.com/aws/aws-sdk-go-v2/service/cloudformation v1.42.6 h1:XdEBz/eAB4K5QyQ9f
github.com/aws/aws-sdk-go-v2/service/cloudformation v1.42.6/go.mod h1:3+AceTAg/X5AUM/SkAbgxzviOBmsGaf9POso/Ymz5vc=
github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs v1.35.4 h1:QSIpvF/tE8Uoy+RNkbMpTahLZHLA1c6vi9tbSE7PZUY=
github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs v1.35.4/go.mod h1:OfO65DNsDX+wgWmjljN55I+Dzo4nbhWNlNFuco5AAgw=
github.com/aws/aws-sdk-go-v2/service/codebuild v1.68.12 h1:lQTVEv/YAk8Rw1Yf4XZS/jNNxF9klCN10WcSR3xlMtU=
github.com/aws/aws-sdk-go-v2/service/codebuild v1.68.12/go.mod h1:yoa0R6Xku788EmJYkFiARzJBxt4A3hgFjQPRmMAttr0=
github.com/aws/aws-sdk-go-v2/service/ec2 v1.145.0 h1:SkSW6wtJmXqJJlBxSc+0mykDdv5nhl9xifMB7JuzNVo=
github.com/aws/aws-sdk-go-v2/service/ec2 v1.145.0/go.mod h1:hIsHE0PaWAQakLCshKS7VKWMGXaqrAFp4m95s2W9E6c=
github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.38.7 h1:NHy1+Jq8gVp8fSLF6Z8SazA+R4Qzsbla/0SbHHReH4Y=
github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.38.7/go.mod h1:KxsaVRXo+DeRMHVp65WqyM49XZiS6n74lEGQindkdgA=
github.com/aws/aws-sdk-go-v2/service/ecs v1.38.1 h1:hfIWClwFGAv6s6HSqqf5AxCToWDkgWe3gC7j4n4Iiew=
github.com/aws/aws-sdk-go-v2/service/ecs v1.38.1/go.mod h1:kt+L4lMA2nvv9evq9S6TOH1up95/2RsQG4GXfxoPRfM=
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.10.4 h1:/b31bi3YVNlkzkBrm9LfpaKoaYZUxIAj4sHfOTmLfqw=
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.10.4/go.mod h1:2aGXHFmbInwgP9ZfpmdIfOELL79zhdNYNmReK8qDfdQ=
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.2.10 h1:L0ai8WICYHozIKK+OtPzVJBugL7culcuM4E4JOpIEm8=
Expand All @@ -104,8 +104,8 @@ github.com/aws/aws-sdk-go-v2/service/ssooidc v1.21.7 h1:QPMJf+Jw8E1l7zqhZmMlFw6w
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.21.7/go.mod h1:ykf3COxYI0UJmxcfcxcVuz7b6uADi1FkiUz6Eb7AgM8=
github.com/aws/aws-sdk-go-v2/service/sts v1.26.7 h1:NzO4Vrau795RkUdSHKEwiR01FaGzGOH1EETJ+5QHnm0=
github.com/aws/aws-sdk-go-v2/service/sts v1.26.7/go.mod h1:6h2YuIoxaMSCFf5fi1EgZAwdfkGMgDY+DVfa61uLe4U=
github.com/aws/smithy-go v1.24.0 h1:LpilSUItNPFr1eY85RYgTIg5eIEPtvFbskaFcmmIUnk=
github.com/aws/smithy-go v1.24.0/go.mod h1:LEj2LM3rBRQJxPZTB4KuzZkaZYnZPnvgIhb4pu07mx0=
github.com/aws/smithy-go v1.24.2 h1:FzA3bu/nt/vDvmnkg+R8Xl46gmzEDam6mZ1hzmwXFng=
github.com/aws/smithy-go v1.24.2/go.mod h1:YE2RhdIuDbA5E5bTdciG9KrW3+TiEONeUWCqxX9i1Fc=
github.com/awslabs/goformation/v7 v7.14.9 h1:sZjjpTqXrcBDz4Fi07JWTT7zKM68XsQkW/7iLAJbA/M=
github.com/awslabs/goformation/v7 v7.14.9/go.mod h1:7obldQ8NQ/AkMsgL5K3l4lRMDFB6kCGUloz5dURcXIs=
github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k=
Expand Down Expand Up @@ -456,8 +456,8 @@ google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822 h1:
google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A=
google.golang.org/grpc v1.73.0 h1:VIWSmpI2MegBtTuFt5/JWy2oXxtjJ/e89Z70ImfD2ok=
google.golang.org/grpc v1.73.0/go.mod h1:50sbHOUqWoCQGI8V2HQLJM0B+LMlIUjNSZmow7EVBQc=
google.golang.org/protobuf v1.36.9 h1:w2gp2mA27hUeUzj9Ex9FBjsBm40zfaDtEWow293U7Iw=
google.golang.org/protobuf v1.36.9/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU=
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
Expand Down
29 changes: 17 additions & 12 deletions src/pkg/auth/interceptor.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package auth

import (
"context"
"net/http"
"strings"

"connectrpc.com/connect"
Expand All @@ -13,32 +14,36 @@ const TenantHeader = "X-Defang-Tenant-Id"
type authInterceptor struct {
authorization string
requestedTenant types.TenantNameOrID
userAgent string
}

func NewAuthInterceptor(token string, requestedTenant types.TenantNameOrID) connect.Interceptor {
func NewAuthInterceptor(token string, requestedTenant types.TenantNameOrID, userAgent string) connect.Interceptor {
// Only tenant ID/name travels over the wire now; org header is retired.
return &authInterceptor{"Bearer " + strings.TrimSpace(token), requestedTenant}
return &authInterceptor{"Bearer " + strings.TrimSpace(token), requestedTenant, userAgent}
}

func (a *authInterceptor) WrapUnary(next connect.UnaryFunc) connect.UnaryFunc {
return func(ctx context.Context, req connect.AnyRequest) (connect.AnyResponse, error) {
req.Header().Set("Authorization", a.authorization)
req.Header().Set("Content-Type", "application/grpc") // same as the gRPC client
if a.requestedTenant.IsSet() {
req.Header().Set(TenantHeader, string(a.requestedTenant))
}
a.setHeaders(req.Header())
return next(ctx, req)
}
}

func (a *authInterceptor) setHeaders(header http.Header) {
if a.userAgent != "" {
header.Set("User-Agent", a.userAgent)
}
header.Set("Authorization", a.authorization)
header.Set("Content-Type", "application/grpc") // same as the gRPC client
if a.requestedTenant.IsSet() {
header.Set(TenantHeader, string(a.requestedTenant))
}
}

func (a *authInterceptor) WrapStreamingClient(next connect.StreamingClientFunc) connect.StreamingClientFunc {
return func(ctx context.Context, spec connect.Spec) connect.StreamingClientConn {
conn := next(ctx, spec)
conn.RequestHeader().Set("Authorization", a.authorization)
conn.RequestHeader().Set("Content-Type", "application/grpc") // same as the gRPC client
if a.requestedTenant.IsSet() {
conn.RequestHeader().Set(TenantHeader, string(a.requestedTenant))
}
a.setHeaders(conn.RequestHeader())
return conn
}
}
Expand Down
98 changes: 43 additions & 55 deletions src/pkg/cli/client/byoc/aws/byoc.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,10 @@ import (
"github.com/DefangLabs/defang/src/pkg/cli/client/byoc"
"github.com/DefangLabs/defang/src/pkg/cli/client/byoc/state"
"github.com/DefangLabs/defang/src/pkg/cli/compose"
"github.com/DefangLabs/defang/src/pkg/clouds"
"github.com/DefangLabs/defang/src/pkg/clouds/aws"
awscodebuild "github.com/DefangLabs/defang/src/pkg/clouds/aws/codebuild"
"github.com/DefangLabs/defang/src/pkg/clouds/aws/codebuild/cfn"
"github.com/DefangLabs/defang/src/pkg/clouds/aws/cw"
"github.com/DefangLabs/defang/src/pkg/clouds/aws/ecs"
"github.com/DefangLabs/defang/src/pkg/clouds/aws/ecs/cfn"
"github.com/DefangLabs/defang/src/pkg/dns"
"github.com/DefangLabs/defang/src/pkg/dockerhub"
"github.com/DefangLabs/defang/src/pkg/http"
Expand Down Expand Up @@ -53,11 +52,11 @@ type Config = awssdk.Config
type ByocAws struct {
*byoc.ByocBaseClient

driver *cfn.AwsEcsCfn // TODO: ecs is stateful, contains the output of the cd cfn stack after SetUpCD
driver *cfn.AwsCfn // TODO: ecs is stateful, contains the output of the cd cfn stack after SetUpCD

cdEtag types.ETag
cdStart time.Time
cdTaskArn ecs.TaskArn // for GetDeploymentStatus
cdBuildId awscodebuild.BuildID // for GetDeploymentStatus

needDockerHubCreds bool
}
Expand Down Expand Up @@ -142,13 +141,8 @@ func (b *ByocAws) Authenticate(ctx context.Context, interactive bool) error {
return b.driver.Authenticate(ctx, interactive)
}

func (b *ByocAws) makeContainers() []clouds.Container {
return makeContainers(b.PulumiVersion, b.CDImage)
}

func (b *ByocAws) PrintCloudFormationTemplate() ([]byte, error) {
containers := b.makeContainers()
template, err := cfn.CreateTemplate(byoc.CdTaskPrefix, containers)
template, err := cfn.CreateTemplate(byoc.CdTaskPrefix)
if err != nil {
return nil, err
}
Expand All @@ -162,34 +156,30 @@ func (b *ByocAws) SetUpCD(ctx context.Context, force bool) error {

term.Debugf("Using CD image: %q", b.CDImage)

created, err := b.driver.SetUp(ctx, b.makeContainers(), force)
_, err := b.driver.SetUp(ctx, force)
if err != nil {
return AnnotateAwsError(err)
}

// Delete default SecurityGroup rules to comply with stricter AWS account security policies;
// only needed when the stack (and its VPC) is first created.
if created {
if sgId := b.driver.DefaultSecurityGroupID; sgId != "" {
term.Debugf("Cleaning up default Security Group rules (%s)", sgId)
if err := b.driver.RevokeDefaultSecurityGroupRules(ctx, sgId); err != nil {
term.Warnf("Could not clean up default Security Group rules: %v", err)
}
}
}

b.SetupDone = true
return nil
}

func (*ByocAws) Driver() string {
return "codebuild"
}

func (b *ByocAws) GetDeploymentStatus(ctx context.Context) (bool, error) {
done, err := b.driver.GetTaskStatus(ctx, b.cdTaskArn)
cfg, err := b.driver.LoadConfig(ctx)
if err != nil {
return false, AnnotateAwsError(err)
}
done, err := awscodebuild.GetBuildStatus(ctx, cfg, b.cdBuildId)
if err != nil {
// check if the task failed; if so, return the a ErrDeploymentFailed error
if taskErr := new(ecs.TaskFailure); errors.As(err, taskErr) {
return done, client.ErrDeploymentFailed{Message: taskErr.Error()}
if buildErr := new(awscodebuild.BuildFailure); errors.As(err, buildErr) {
return done, client.ErrDeploymentFailed{Message: buildErr.Error()}
}
return done, err
return done, AnnotateAwsError(err)
}
Comment thread
lionello marked this conversation as resolved.
return done, nil
}
Expand Down Expand Up @@ -288,13 +278,13 @@ func (b *ByocAws) deploy(ctx context.Context, req *client.DeployRequest, cmd str
}
}

cdTaskArn, err := b.runCdCommand(ctx, cdCmd)
cdBuildId, err := b.runCdCommand(ctx, cdCmd)
if err != nil {
return nil, AnnotateAwsError(err)
}
b.cdEtag = etag
b.cdStart = time.Now()
b.cdTaskArn = cdTaskArn
b.cdBuildId = cdBuildId

for _, si := range serviceInfos {
if si.UseAcmeCert {
Expand Down Expand Up @@ -322,7 +312,7 @@ func (b *ByocAws) putDockerHubSecret(ctx context.Context, projectName string, us

cfg, err := b.driver.LoadConfig(ctx)
if err != nil {
return "", err
return "", AnnotateAwsError(err)
}

secretsmanagerClient := secretsmanager.NewFromConfig(cfg)
Expand Down Expand Up @@ -535,7 +525,7 @@ type cdCommand struct {
eventsUrl string
}

func (b *ByocAws) runCdCommand(ctx context.Context, cmd cdCommand) (ecs.TaskArn, error) {
func (b *ByocAws) runCdCommand(ctx context.Context, cmd cdCommand) (awscodebuild.BuildID, error) {
// Setup the deployment environment
env, err := b.environment(cmd.project)
if err != nil {
Expand Down Expand Up @@ -586,7 +576,9 @@ func (b *ByocAws) runCdCommand(ctx context.Context, cmd cdCommand) (ecs.TaskArn,
env["DEFANG_EVENTS_UPLOAD_URL"] = cmd.eventsUrl
}

return b.driver.Run(ctx, env, cmd.command...)
// Prepend the entrypoint; CodeBuild runs buildspec commands in a shell, not via Docker ENTRYPOINT
args := append([]string{"node", "lib/index.js"}, cmd.command...)
return b.driver.Run(ctx, "/app", b.CDImage, env, args...)
}

func (b *ByocAws) GetProjectUpdate(ctx context.Context, projectName string) (*defangv1.ProjectUpdate, error) {
Expand Down Expand Up @@ -722,8 +714,8 @@ func (b *ByocAws) QueryLogs(ctx context.Context, req *defangv1.TailRequest) (ite
// * Valid Etag, no services: tail all tasks/services with that Etag
// * Valid Etag, service: tail that task/service
var logSeq iter.Seq2[cw.LogEvent, error]
if taskID := b.deriveTaskID(req.Etag); taskID != "" && logs.LogType(req.LogType) == logs.LogTypeCD {
cdSeq, err := b.queryOrTailLogsByTaskID(ctx, cwClient, req, taskID)
if buildID := b.deriveBuildID(req.Etag); buildID != nil && logs.LogType(req.LogType) == logs.LogTypeCD {
cdSeq, err := b.queryOrTailLogsByBuildID(ctx, cwClient, req, buildID)
if err != nil {
return nil, AnnotateAwsError(err)
}
Expand Down Expand Up @@ -761,32 +753,28 @@ func (b *ByocAws) QueryLogs(ctx context.Context, req *defangv1.TailRequest) (ite
}, nil
}

func (b *ByocAws) queryOrTailLogsByTaskID(ctx context.Context, cwClient cw.LogsClient, req *defangv1.TailRequest, taskID string) (iter.Seq2[[]cw.LogEvent, error], error) {
if b.cdTaskArn == nil {
var err error
b.cdTaskArn, err = b.driver.GetTaskArn(taskID) // only fails on missing task ID
if err != nil {
return nil, err
}
}
func (b *ByocAws) queryOrTailLogsByBuildID(ctx context.Context, cwClient cw.LogsClient, req *defangv1.TailRequest, buildID awscodebuild.BuildID) (iter.Seq2[[]cw.LogEvent, error], error) {
if req.Follow {
return b.driver.TailTaskID(ctx, cwClient, taskID)
return b.driver.TailBuildID(ctx, cwClient, buildID)
} else {
start := timeutils.AsTime(req.Since, time.Time{})
end := timeutils.AsTime(req.Until, time.Time{})
return b.driver.QueryTaskID(ctx, cwClient, taskID, start, end, req.Limit)
return b.driver.QueryBuildID(ctx, cwClient, buildID, start, end, req.Limit)
}
}

// deriveTaskID returns the CD task ID if the etag refers to a CD task, or empty string otherwise.
func (b *ByocAws) deriveTaskID(reqEtag string) string {
if b.cdTaskArn != nil && b.cdEtag == reqEtag {
return ecs.GetTaskID(b.cdTaskArn)
// deriveBuildID returns the BuildID if the etag refers to a CD CodeBuild build, or nil otherwise.
func (b *ByocAws) deriveBuildID(reqEtag string) awscodebuild.BuildID {
if reqEtag == "" {
return nil
}
if b.cdBuildId != nil && b.cdEtag == reqEtag {
return b.cdBuildId
}
if _, err := types.ParseEtag(reqEtag); err != nil {
return reqEtag // legacy: assume invalid etag is a task ID
return awscodebuild.BuildID(&reqEtag) // legacy: assume invalid etag is a task ID
}
return ""
return nil
}

func (b *ByocAws) queryOrTailLogs(ctx context.Context, cwClient cw.LogsClient, req *defangv1.TailRequest) (iter.Seq2[cw.LogEvent, error], error) {
Expand Down Expand Up @@ -862,8 +850,8 @@ func (b *ByocAws) getLogGroupInputs(etag types.ETag, projectName, service, filte
} else {
cdTail := cw.LogGroupInput{LogGroupARN: b.driver.LogGroupARN, LogEventFilterPattern: pattern}
// If we know the CD task ARN, only tail the logstream for that CD task; FIXME: store the task ID in the project's ProjectUpdate in S3 and use that
if b.cdTaskArn != nil && (b.cdEtag == etag || ecs.GetTaskID(b.cdTaskArn) == etag) {
cdTail.LogStreamNames = []string{ecs.GetCDLogStreamForTaskID(ecs.GetTaskID(b.cdTaskArn))}
if b.cdBuildId != nil && (b.cdEtag == etag || *b.cdBuildId == etag) {
cdTail.LogStreamNames = []string{awscodebuild.GetLogStreamForBuildID(b.cdBuildId)}
}
groups = append(groups, cdTail)
term.Debug("Query CD logs", cdTail.LogGroupARN, cdTail.LogStreamNames, filter)
Expand Down Expand Up @@ -926,13 +914,13 @@ func (b *ByocAws) CdCommand(ctx context.Context, req client.CdCommandRequest) (s
statesUrl: req.StatesUrl,
eventsUrl: req.EventsUrl,
}
cdTaskArn, err := b.runCdCommand(ctx, cmd)
cdBuildId, err := b.runCdCommand(ctx, cmd)
if err != nil {
return "", AnnotateAwsError(err)
}
b.cdEtag = etag
b.cdStart = time.Now()
b.cdTaskArn = cdTaskArn
b.cdBuildId = cdBuildId
return etag, nil
}

Expand Down
Loading
Loading