Add standalone capacility

Signed-off-by: Ulysses Souza <ulyssessouza@gmail.com>
This commit is contained in:
Ulysses Souza 2021-09-29 23:45:11 +02:00
parent 6e9d9bf86d
commit 17354fcc99
3 changed files with 56 additions and 12 deletions

View File

@ -25,15 +25,14 @@ import (
"strings" "strings"
"syscall" "syscall"
"github.com/docker/compose/v2/cmd/formatter"
"github.com/sirupsen/logrus"
"github.com/compose-spec/compose-go/cli" "github.com/compose-spec/compose-go/cli"
"github.com/compose-spec/compose-go/types" "github.com/compose-spec/compose-go/types"
dockercli "github.com/docker/cli/cli" dockercli "github.com/docker/cli/cli"
"github.com/docker/cli/cli-plugins/manager"
"github.com/docker/compose/v2/cmd/formatter"
"github.com/morikuni/aec" "github.com/morikuni/aec"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/sirupsen/logrus"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/spf13/pflag" "github.com/spf13/pflag"
@ -106,7 +105,7 @@ type ProjectFunc func(ctx context.Context, project *types.Project) error
// ProjectServicesFunc does stuff within a types.Project and a selection of services // ProjectServicesFunc does stuff within a types.Project and a selection of services
type ProjectServicesFunc func(ctx context.Context, project *types.Project, services []string) error type ProjectServicesFunc func(ctx context.Context, project *types.Project, services []string) error
// WithServices creates a cobra run command from a ProjectFunc based on configured project options and selected services // WithProject creates a cobra run command from a ProjectFunc based on configured project options and selected services
func (o *projectOptions) WithProject(fn ProjectFunc) func(cmd *cobra.Command, args []string) error { func (o *projectOptions) WithProject(fn ProjectFunc) func(cmd *cobra.Command, args []string) error {
return o.WithServices(func(ctx context.Context, project *types.Project, services []string) error { return o.WithServices(func(ctx context.Context, project *types.Project, services []string) error {
return fn(ctx, project) return fn(ctx, project)
@ -209,6 +208,13 @@ func (o *projectOptions) toProjectOptions(po ...cli.ProjectOptionsFn) (*cli.Proj
cli.WithName(o.ProjectName))...) cli.WithName(o.ProjectName))...)
} }
const pluginName = "compose"
// RunningAsStandalone detects when running as a standalone program
func RunningAsStandalone() bool {
return len(os.Args) < 2 || os.Args[1] != manager.MetadataSubcommandName && os.Args[1] != pluginName
}
// RootCommand returns the compose command with its child commands // RootCommand returns the compose command with its child commands
func RootCommand(backend api.Service) *cobra.Command { func RootCommand(backend api.Service) *cobra.Command {
opts := projectOptions{} opts := projectOptions{}
@ -217,9 +223,14 @@ func RootCommand(backend api.Service) *cobra.Command {
noAnsi bool noAnsi bool
verbose bool verbose bool
) )
commandName := pluginName
if RunningAsStandalone() {
commandName = os.Args[0]
}
command := &cobra.Command{ command := &cobra.Command{
Short: "Docker Compose", Short: "Docker Compose",
Use: "compose", Use: commandName,
TraverseChildren: true, TraverseChildren: true,
// By default (no Run/RunE in parent command) for typos in subcommands, cobra displays the help of parent command but exit(0) ! // By default (no Run/RunE in parent command) for typos in subcommands, cobra displays the help of parent command but exit(0) !
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(cmd *cobra.Command, args []string) error {
@ -234,11 +245,13 @@ func RootCommand(backend api.Service) *cobra.Command {
}, },
PersistentPreRunE: func(cmd *cobra.Command, args []string) error { PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
parent := cmd.Root() parent := cmd.Root()
parentPrerun := parent.PersistentPreRunE if parent != nil && parent.Name() != commandName {
if parentPrerun != nil { parentPrerun := parent.PersistentPreRunE
err := parentPrerun(cmd, args) if parentPrerun != nil {
if err != nil { err := parentPrerun(cmd, args)
return err if err != nil {
return err
}
} }
} }
if noAnsi { if noAnsi {

View File

@ -17,12 +17,16 @@
package main package main
import ( import (
"fmt"
"os"
dockercli "github.com/docker/cli/cli" dockercli "github.com/docker/cli/cli"
"github.com/docker/cli/cli-plugins/manager" "github.com/docker/cli/cli-plugins/manager"
"github.com/docker/cli/cli-plugins/plugin" "github.com/docker/cli/cli-plugins/plugin"
"github.com/docker/cli/cli/command" "github.com/docker/cli/cli/command"
"github.com/spf13/cobra" "github.com/spf13/cobra"
cliFlags "github.com/docker/cli/cli/flags"
commands "github.com/docker/compose/v2/cmd/compose" commands "github.com/docker/compose/v2/cmd/compose"
"github.com/docker/compose/v2/internal" "github.com/docker/compose/v2/internal"
"github.com/docker/compose/v2/pkg/api" "github.com/docker/compose/v2/pkg/api"
@ -34,7 +38,26 @@ func init() {
"To provide feedback or request new features please open issues at https://github.com/docker/compose" "To provide feedback or request new features please open issues at https://github.com/docker/compose"
} }
func main() { func standaloneMain() int {
dockerCli, err := command.NewDockerCli()
if err != nil {
_, _ = fmt.Fprintln(os.Stderr, err)
return 1
}
opts := cliFlags.NewClientOptions()
err = dockerCli.Initialize(opts)
if err != nil {
return 1
}
lazyInit := api.NewServiceProxy().WithService(compose.NewComposeService(dockerCli.Client(), dockerCli.ConfigFile()))
rootCmd := commands.RootCommand(lazyInit)
if err := rootCmd.Execute(); err != nil {
return 1
}
return 0
}
func pluginMain() {
plugin.Run(func(dockerCli command.Cli) *cobra.Command { plugin.Run(func(dockerCli command.Cli) *cobra.Command {
lazyInit := api.NewServiceProxy() lazyInit := api.NewServiceProxy()
cmd := commands.RootCommand(lazyInit) cmd := commands.RootCommand(lazyInit)
@ -63,3 +86,10 @@ func main() {
Version: internal.Version, Version: internal.Version,
}) })
} }
func main() {
if commands.RunningAsStandalone() {
os.Exit(standaloneMain())
}
pluginMain()
}

View File

@ -32,6 +32,7 @@ import (
"github.com/sanathkr/go-yaml" "github.com/sanathkr/go-yaml"
) )
// Separator is used for naming components
var Separator = "-" var Separator = "-"
// NewComposeService create a local implementation of the compose.Service API // NewComposeService create a local implementation of the compose.Service API