diff --git a/aci/backend.go b/aci/backend.go index 359d5ef64..319bbf9c9 100644 --- a/aci/backend.go +++ b/aci/backend.go @@ -39,6 +39,7 @@ import ( "github.com/docker/api/context/cloud" "github.com/docker/api/context/store" "github.com/docker/api/errdefs" + ecstypes "github.com/docker/ecs-plugin/pkg/compose" ) const ( @@ -366,6 +367,14 @@ func (cs *aciComposeService) Down(ctx context.Context, opts cli.ProjectOptions) return err } +func (cs *aciComposeService) Ps(ctx context.Context, opts cli.ProjectOptions) ([]ecstypes.ServiceStatus, error) { + return nil, errdefs.ErrNotImplemented +} + +func (cs *aciComposeService) Logs(ctx context.Context, opts cli.ProjectOptions) error { + return errdefs.ErrNotImplemented +} + type aciCloudService struct { loginService login.AzureLoginService } diff --git a/cli/cmd/compose/compose.go b/cli/cmd/compose/compose.go index 5c57e5412..f2afad296 100644 --- a/cli/cmd/compose/compose.go +++ b/cli/cmd/compose/compose.go @@ -41,6 +41,8 @@ func Command() *cobra.Command { command.AddCommand( upCommand(), downCommand(), + psCommand(), + logsCommand(), ) return command diff --git a/cli/cmd/compose/logs.go b/cli/cmd/compose/logs.go new file mode 100644 index 000000000..15e0a2600 --- /dev/null +++ b/cli/cmd/compose/logs.go @@ -0,0 +1,56 @@ +/* + Copyright 2020 Docker, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package compose + +import ( + "context" + "errors" + + "github.com/compose-spec/compose-go/cli" + "github.com/spf13/cobra" + + "github.com/docker/api/client" +) + +func logsCommand() *cobra.Command { + opts := cli.ProjectOptions{} + logsCmd := &cobra.Command{ + Use: "logs", + RunE: func(cmd *cobra.Command, args []string) error { + return runLogs(cmd.Context(), opts) + }, + } + logsCmd.Flags().StringVarP(&opts.Name, "project-name", "p", "", "Project name") + logsCmd.Flags().StringVar(&opts.WorkingDir, "workdir", ".", "Work dir") + logsCmd.Flags().StringArrayVarP(&opts.ConfigPaths, "file", "f", []string{}, "Compose configuration files") + + return logsCmd +} + +func runLogs(ctx context.Context, opts cli.ProjectOptions) error { + c, err := client.New(ctx) + if err != nil { + return err + } + + composeService := c.ComposeService() + if composeService == nil { + return errors.New("compose not implemented in current context") + } + + return composeService.Logs(ctx, opts) +} diff --git a/cli/cmd/compose/ps.go b/cli/cmd/compose/ps.go new file mode 100644 index 000000000..ed726b855 --- /dev/null +++ b/cli/cmd/compose/ps.go @@ -0,0 +1,77 @@ +/* + Copyright 2020 Docker, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package compose + +import ( + "context" + "errors" + "fmt" + "io" + "os" + "strings" + "text/tabwriter" + + "github.com/compose-spec/compose-go/cli" + "github.com/spf13/cobra" + + "github.com/docker/api/client" +) + +func psCommand() *cobra.Command { + opts := cli.ProjectOptions{} + psCmd := &cobra.Command{ + Use: "ps", + RunE: func(cmd *cobra.Command, args []string) error { + return runPs(cmd.Context(), opts) + }, + } + psCmd.Flags().StringVarP(&opts.Name, "project-name", "p", "", "Project name") + psCmd.Flags().StringVar(&opts.WorkingDir, "workdir", ".", "Work dir") + psCmd.Flags().StringArrayVarP(&opts.ConfigPaths, "file", "f", []string{}, "Compose configuration files") + + return psCmd +} + +func runPs(ctx context.Context, opts cli.ProjectOptions) error { + c, err := client.New(ctx) + if err != nil { + return err + } + + composeService := c.ComposeService() + if composeService == nil { + return errors.New("compose not implemented in current context") + } + + serviceList, err := composeService.Ps(ctx, opts) + if err != nil { + return err + } + printSection(os.Stdout, len(serviceList), func(w io.Writer) { + for _, service := range serviceList { + fmt.Fprintf(w, "%s\t%s\t%d/%d\t%s\n", service.ID, service.Name, service.Replicas, service.Desired, strings.Join(service.Ports, ", ")) + } + }, "ID", "NAME", "REPLICAS", "PORTS") + return nil +} + +func printSection(out io.Writer, len int, printer func(io.Writer), headers ...string) { + w := tabwriter.NewWriter(out, 20, 1, 3, ' ', 0) + fmt.Fprintln(w, strings.Join(headers, "\t")) + printer(w) + w.Flush() +} diff --git a/compose/api.go b/compose/api.go index b08384ec9..7d2d7244d 100644 --- a/compose/api.go +++ b/compose/api.go @@ -20,6 +20,7 @@ import ( "context" "github.com/compose-spec/compose-go/cli" + types "github.com/docker/ecs-plugin/pkg/compose" ) // Service manages a compose project @@ -28,4 +29,6 @@ type Service interface { Up(ctx context.Context, opts cli.ProjectOptions) error // Down executes the equivalent to a `compose down` Down(ctx context.Context, opts cli.ProjectOptions) error + Logs(ctx context.Context, projectName cli.ProjectOptions) error + Ps(background context.Context, options cli.ProjectOptions) ([]types.ServiceStatus, error) } diff --git a/example/backend.go b/example/backend.go index 0db8f1e3b..997894820 100644 --- a/example/backend.go +++ b/example/backend.go @@ -26,10 +26,12 @@ import ( "github.com/compose-spec/compose-go/cli" "github.com/docker/api/context/cloud" + "github.com/docker/api/errdefs" "github.com/docker/api/backend" "github.com/docker/api/compose" "github.com/docker/api/containers" + ecstypes "github.com/docker/ecs-plugin/pkg/compose" ) type apiService struct { @@ -129,3 +131,10 @@ func (cs *composeService) Down(ctx context.Context, opts cli.ProjectOptions) err fmt.Printf("Down command on project %q", prj.Name) return nil } +func (cs *composeService) Ps(ctx context.Context, opts cli.ProjectOptions) ([]ecstypes.ServiceStatus, error) { + return nil, errdefs.ErrNotImplemented +} + +func (cs *composeService) Logs(ctx context.Context, opts cli.ProjectOptions) error { + return errdefs.ErrNotImplemented +}