diff --git a/local/compose.go b/local/compose.go index 8cb57de2e..41bd38750 100644 --- a/local/compose.go +++ b/local/compose.go @@ -20,20 +20,25 @@ package local import ( "context" + "encoding/json" "fmt" "github.com/compose-spec/compose-go/types" "github.com/docker/compose-cli/api/compose" + "github.com/docker/compose-cli/api/containers" 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/mount" "github.com/docker/docker/api/types/network" "github.com/docker/docker/api/types/strslice" "github.com/docker/docker/errdefs" "github.com/docker/go-connections/nat" "github.com/pkg/errors" + "github.com/sanathkr/go-yaml" "io" "path/filepath" "strings" + "sync" ) func (s *local) Up(ctx context.Context, project *types.Project, detach bool) error { @@ -75,26 +80,89 @@ func (s *local) Up(ctx context.Context, project *types.Project, detach bool) err func (s *local) Down(ctx context.Context, projectName string) error { - panic("implement me") + list, err := s.containerService.apiClient.ContainerList(ctx, moby.ContainerListOptions{ + Filters: filters.NewArgs( + filters.Arg("label", "com.docker.compose.project="+projectName), + ), + }) + if err != nil { + return err + } + for _, c := range list { + s.containerService.Stop(ctx, c.ID, nil) + } + return nil } func (s *local) Logs(ctx context.Context, projectName string, w io.Writer) error { - panic("implement me") + list, err := s.containerService.apiClient.ContainerList(ctx, moby.ContainerListOptions{ + Filters: filters.NewArgs( + filters.Arg("label", "com.docker.compose.project="+projectName), + ), + }) + if err != nil { + return err + } + var wg sync.WaitGroup + for _, c := range list { + go func() { + s.containerService.Logs(ctx, c.ID, containers.LogsRequest{ + Follow: true, + Writer: w, + }) + wg.Done() + }() + wg.Add(1) + } + wg.Wait() + return nil } func (s *local) Ps(ctx context.Context, projectName string) ([]compose.ServiceStatus, error) { - panic("implement me") + list, err := s.containerService.apiClient.ContainerList(ctx, moby.ContainerListOptions{ + Filters: filters.NewArgs( + filters.Arg("label", "com.docker.compose.project="+projectName), + ), + }) + if err != nil { + return nil, err + } + var status []compose.ServiceStatus + for _,c := range list { + // TODO group by service + status = append(status, compose.ServiceStatus{ + ID: c.ID, + Name: c.Labels["com.docker.compose.service"], + Replicas: 0, + Desired: 0, + Ports: nil, + Publishers: nil, + }) + } + return status, nil } func (s *local) List(ctx context.Context, projectName string) ([]compose.Stack, error) { - panic("implement me") + _, err := s.containerService.apiClient.ContainerList(ctx, moby.ContainerListOptions{All: true}) + if err != nil { + return nil, err + } + var stacks []compose.Stack + // TODO rebuild stacks based on containers + return stacks, nil } func (s *local) Convert(ctx context.Context, project *types.Project, format string) ([]byte, error) { - panic("implement me") + switch format { + case "json": + return json.MarshalIndent(project, "", " ") + case "yaml": + return yaml.Marshal(project) + default: + return nil, fmt.Errorf("unsupported format %q", format) + } } - func getContainerCreateOptions(p *types.Project, s types.ServiceConfig) (*container.Config, *container.HostConfig, *network.NetworkingConfig, error) { labels := map[string]string{ "com.docker.compose.project": p.Name,