diff --git a/go.mod b/go.mod index 5ee24a519..0b4c00c70 100644 --- a/go.mod +++ b/go.mod @@ -17,7 +17,7 @@ require ( github.com/awslabs/goformation/v4 v4.15.6 github.com/buger/goterm v1.0.0 github.com/cnabio/cnab-to-oci v0.3.1-beta1 - github.com/compose-spec/compose-go v0.0.0-20210412113016-e35895260882 + github.com/compose-spec/compose-go v0.0.0-20210421142148-66b18e67d2c0 github.com/containerd/console v1.0.1 github.com/containerd/containerd v1.4.3 github.com/containerd/continuity v0.0.0-20200928162600-f2cc35102c2a // indirect diff --git a/go.sum b/go.sum index 2944374d8..2cf9ecfa0 100644 --- a/go.sum +++ b/go.sum @@ -308,8 +308,8 @@ github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGX github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= github.com/codahale/hdrhistogram v0.0.0-20160425231609-f8ad88b59a58/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= -github.com/compose-spec/compose-go v0.0.0-20210412113016-e35895260882 h1:vLKOiHY9QPS1eiBvGfsEI7wR23B1bGNvwOF5aVl25Fs= -github.com/compose-spec/compose-go v0.0.0-20210412113016-e35895260882/go.mod h1:6eIT9U2OgdHmkRD6szmqatCrWWEEUSwl/j2iJYH4jLo= +github.com/compose-spec/compose-go v0.0.0-20210421142148-66b18e67d2c0 h1:aoUSQGFmWi8dn1OfT4H5Mx48u5wHt+n07nLFw5j1JXs= +github.com/compose-spec/compose-go v0.0.0-20210421142148-66b18e67d2c0/go.mod h1:6eIT9U2OgdHmkRD6szmqatCrWWEEUSwl/j2iJYH4jLo= github.com/containerd/cgroups v0.0.0-20190919134610-bf292b21730f/go.mod h1:OApqhQ4XNSNC13gXIwDjhOQxjWa/NxkwZXJ1EvqT0ko= github.com/containerd/cgroups v0.0.0-20200531161412-0dbf7f05ba59/go.mod h1:pA0z1pT8KYB3TCXK/ocprsh7MAkoW8bZVzPdih9snmM= github.com/containerd/cgroups v0.0.0-20200710171044-318312a37340 h1:9atoWyI9RtXFwf7UDbme/6M8Ud0rFrx+Q3ZWgSnsxtw= diff --git a/local/compose/build.go b/local/compose/build.go index 168bafa20..5afb17116 100644 --- a/local/compose/build.go +++ b/local/compose/build.go @@ -19,9 +19,7 @@ package compose import ( "context" "fmt" - "net/url" "os" - "path" "strings" "github.com/compose-spec/compose-go/types" @@ -50,7 +48,7 @@ func (s *composeService) Build(ctx context.Context, project *types.Project, opti if service.Build != nil { imageName := getImageName(service, project.Name) imagesToBuild = append(imagesToBuild, imageName) - buildOptions, err := s.toBuildOptions(service, project.WorkingDir, imageName) + buildOptions, err := s.toBuildOptions(service, imageName) if err != nil { return err } @@ -132,7 +130,7 @@ func (s *composeService) getBuildOptions(project *types.Project, images map[stri continue } imagesToBuild = append(imagesToBuild, imageName) - opt, err := s.toBuildOptions(service, project.WorkingDir, imageName) + opt, err := s.toBuildOptions(service, imageName) if err != nil { return nil, nil, err } @@ -257,13 +255,10 @@ func (s *composeService) build(ctx context.Context, project *types.Project, opts return imagesBuilt, err } -func (s *composeService) toBuildOptions(service types.ServiceConfig, contextPath string, imageTag string) (build.Options, error) { +func (s *composeService) toBuildOptions(service types.ServiceConfig, imageTag string) (build.Options, error) { var tags []string tags = append(tags, imageTag) - if service.Build.Dockerfile == "" { - service.Build.Dockerfile = "Dockerfile" - } var buildArgs map[string]string var plats []specs.Platform @@ -275,22 +270,11 @@ func (s *composeService) toBuildOptions(service types.ServiceConfig, contextPath plats = append(plats, p) } - var input build.Inputs - _, err := url.ParseRequestURI(service.Build.Context) - if err == nil { - input = build.Inputs{ + return build.Options{ + Inputs: build.Inputs{ ContextPath: service.Build.Context, DockerfilePath: service.Build.Dockerfile, - } - } else { - input = build.Inputs{ - ContextPath: path.Join(contextPath, service.Build.Context), - DockerfilePath: path.Join(contextPath, service.Build.Context, service.Build.Dockerfile), - } - } - - return build.Options{ - Inputs: input, + }, BuildArgs: flatten(mergeArgs(service.Build.Args, buildArgs)), Tags: tags, Target: service.Build.Target, diff --git a/local/compose/convergence.go b/local/compose/convergence.go index 4a19c15a5..d55d1e976 100644 --- a/local/compose/convergence.go +++ b/local/compose/convergence.go @@ -25,10 +25,10 @@ import ( "github.com/compose-spec/compose-go/types" "github.com/containerd/containerd/platforms" moby "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/container" "github.com/docker/docker/api/types/filters" "github.com/docker/docker/api/types/network" specs "github.com/opencontainers/image-spec/specs-go/v1" + "github.com/sirupsen/logrus" "golang.org/x/sync/errgroup" "github.com/docker/compose-cli/api/compose" @@ -147,13 +147,13 @@ func getContainerProgressName(container moby.Container) string { func (s *composeService) waitDependencies(ctx context.Context, project *types.Project, service types.ServiceConfig) error { eg, _ := errgroup.WithContext(ctx) for dep, config := range service.DependsOn { - switch config.Condition { - case "service_healthy": - eg.Go(func() error { - ticker := time.NewTicker(500 * time.Millisecond) - defer ticker.Stop() - for { - <-ticker.C + eg.Go(func() error { + ticker := time.NewTicker(500 * time.Millisecond) + defer ticker.Stop() + for { + <-ticker.C + switch config.Condition { + case types.ServiceConditionHealthy: healthy, err := s.isServiceHealthy(ctx, project, dep) if err != nil { return err @@ -161,17 +161,26 @@ func (s *composeService) waitDependencies(ctx context.Context, project *types.Pr if healthy { return nil } + case types.ServiceConditionCompletedSuccessfully: + exited, code, err := s.isServiceCompleted(ctx, project, dep) + if err != nil { + return err + } + if exited { + if code != 0 { + return fmt.Errorf("service %q didn't completed successfully: exit %d", dep, code) + } + return nil + } + case types.ServiceConditionStarted: + // already managed by InDependencyOrder + return nil + default: + logrus.Warnf("unsupported depends_on condition: %s", config.Condition) + return nil } - }) - case "service_completed_successfully": - exit, err := s.waitCompleted(ctx, project, dep) - if err != nil { - return err } - if exit != 0 { - return fmt.Errorf("service %q didn't completed successfully: exit %d", dep, exit) - } - } + }) } return eg.Wait() } @@ -360,26 +369,21 @@ func (s *composeService) isServiceHealthy(ctx context.Context, project *types.Pr return true, nil } -func (s *composeService) waitCompleted(ctx context.Context, project *types.Project, dep string) (int64, error) { - containers, err := s.apiClient.ContainerList(ctx, moby.ContainerListOptions{ - Filters: filters.NewArgs( - projectFilter(project.Name), - serviceFilter(dep), - ), - }) +func (s *composeService) isServiceCompleted(ctx context.Context, project *types.Project, dep string) (bool, int, error) { + containers, err := s.getContainers(ctx, project.Name, oneOffExclude, true, dep) if err != nil { - return 0, err + return false, 0, err } for _, c := range containers { - wait, errors := s.apiClient.ContainerWait(ctx, c.ID, container.WaitConditionNextExit) - select { - case w := <-wait: - return w.StatusCode, nil - case err := <-errors: - return 0, err + container, err := s.apiClient.ContainerInspect(ctx, c.ID) + if err != nil { + return false, 0, err + } + if container.State != nil && container.State.Status == "exited" { + return true, container.State.ExitCode, nil } } - return 0, nil + return false, 0, nil } func (s *composeService) startService(ctx context.Context, project *types.Project, service types.ServiceConfig) error {