diff --git a/cmd/compose/compose.go b/cmd/compose/compose.go index bf30975c08..d8428e603c 100644 --- a/cmd/compose/compose.go +++ b/cmd/compose/compose.go @@ -47,6 +47,19 @@ import ( "github.com/docker/compose/v2/pkg/utils" ) +const ( + // ComposeParallelLimit set the limit running concurrent operation on docker engine + ComposeParallelLimit = "COMPOSE_PARALLEL_LIMIT" + // ComposeProjectName define the project name to be used, instead of guessing from parent directory + ComposeProjectName = "COMPOSE_PROJECT_NAME" + // ComposeCompatibility try to mimic compose v1 as much as possible + ComposeCompatibility = "COMPOSE_COMPATIBILITY" + // ComposeRemoveOrphans remove “orphaned" containers, i.e. containers tagged for current project but not declared as service + ComposeRemoveOrphans = "COMPOSE_REMOVE_ORPHANS" + // ComposeIgnoreOrphans ignore "orphaned" containers + ComposeIgnoreOrphans = "COMPOSE_IGNORE_ORPHANS" +) + // Command defines a compose CLI command as a func with args type Command func(context.Context, []string) error @@ -145,7 +158,7 @@ func (o *ProjectOptions) projectOrName(services ...string) (*types.Project, stri if len(o.ConfigPaths) > 0 || o.ProjectName == "" { p, err := o.ToProject(services, cli.WithDiscardEnvFile) if err != nil { - envProjectName := os.Getenv("COMPOSE_PROJECT_NAME") + envProjectName := os.Getenv(ComposeProjectName) if envProjectName != "" { return nil, envProjectName, nil } @@ -162,7 +175,7 @@ func (o *ProjectOptions) toProjectName() (string, error) { return o.ProjectName, nil } - envProjectName := os.Getenv("COMPOSE_PROJECT_NAME") + envProjectName := os.Getenv("ComposeProjectName") if envProjectName != "" { return envProjectName, nil } @@ -180,7 +193,7 @@ func (o *ProjectOptions) ToProject(services []string, po ...cli.ProjectOptionsFn return nil, compose.WrapComposeError(err) } - if o.Compatibility || utils.StringToBool(options.Environment["COMPOSE_COMPATIBILITY"]) { + if o.Compatibility || utils.StringToBool(options.Environment[ComposeCompatibility]) { api.Separator = "_" } @@ -339,10 +352,22 @@ func RootCommand(streams command.Cli, backend api.Service) *cobra.Command { //no opts.EnvFiles[i] = file } } - if v, ok := os.LookupEnv("COMPOSE_PARALLEL_LIMIT"); ok && !cmd.Flags().Changed("parallel") { + + composeCmd := cmd + for { + if composeCmd.Name() == PluginName { + break + } + if !composeCmd.HasParent() { + return fmt.Errorf("error parsing command line, expected %q", PluginName) + } + composeCmd = composeCmd.Parent() + } + + if v, ok := os.LookupEnv(ComposeParallelLimit); ok && !composeCmd.Flags().Changed("parallel") { i, err := strconv.Atoi(v) if err != nil { - return fmt.Errorf("COMPOSE_PARALLEL_LIMIT must be an integer (found: %q)", v) + return fmt.Errorf("%s must be an integer (found: %q)", ComposeParallelLimit, v) } parallel = i } diff --git a/cmd/compose/down.go b/cmd/compose/down.go index e868bbf853..29f7a7c0e6 100644 --- a/cmd/compose/down.go +++ b/cmd/compose/down.go @@ -62,7 +62,7 @@ func downCommand(p *ProjectOptions, backend api.Service) *cobra.Command { ValidArgsFunction: noCompletion(), } flags := downCmd.Flags() - removeOrphans := utils.StringToBool(os.Getenv("COMPOSE_REMOVE_ORPHANS")) + removeOrphans := utils.StringToBool(os.Getenv(ComposeRemoveOrphans)) flags.BoolVar(&opts.removeOrphans, "remove-orphans", removeOrphans, "Remove containers for services not defined in the Compose file.") flags.IntVarP(&opts.timeout, "timeout", "t", 10, "Specify a shutdown timeout in seconds") flags.BoolVarP(&opts.volumes, "volumes", "v", false, "Remove named volumes declared in the `volumes` section of the Compose file and anonymous volumes attached to containers.") diff --git a/cmd/compose/kill.go b/cmd/compose/kill.go index de8e9b8e9e..629db5f63b 100644 --- a/cmd/compose/kill.go +++ b/cmd/compose/kill.go @@ -46,7 +46,7 @@ func killCommand(p *ProjectOptions, backend api.Service) *cobra.Command { } flags := cmd.Flags() - removeOrphans := utils.StringToBool(os.Getenv("COMPOSE_REMOVE_ORPHANS")) + removeOrphans := utils.StringToBool(os.Getenv(ComposeRemoveOrphans)) flags.BoolVar(&opts.removeOrphans, "remove-orphans", removeOrphans, "Remove containers for services not defined in the Compose file.") flags.StringVarP(&opts.signal, "signal", "s", "SIGKILL", "SIGNAL to send to the container.") diff --git a/cmd/compose/run.go b/cmd/compose/run.go index f454ac36d8..1a4137936f 100644 --- a/cmd/compose/run.go +++ b/cmd/compose/run.go @@ -146,7 +146,8 @@ func runCommand(p *ProjectOptions, streams api.Streams, backend api.Service) *co if err != nil { return err } - opts.ignoreOrphans = utils.StringToBool(project.Environment["COMPOSE_IGNORE_ORPHANS"]) + + opts.ignoreOrphans = utils.StringToBool(project.Environment[ComposeIgnoreOrphans]) return runRun(ctx, backend, project, opts, createOpts, streams) }), ValidArgsFunction: completeServiceNames(p), diff --git a/cmd/compose/up.go b/cmd/compose/up.go index 37ebac9679..6894367d04 100644 --- a/cmd/compose/up.go +++ b/cmd/compose/up.go @@ -82,9 +82,9 @@ func upCommand(p *ProjectOptions, streams api.Streams, backend api.Service) *cob return validateFlags(&up, &create) }), RunE: p.WithServices(func(ctx context.Context, project *types.Project, services []string) error { - create.ignoreOrphans = utils.StringToBool(project.Environment["COMPOSE_IGNORE_ORPHANS"]) + create.ignoreOrphans = utils.StringToBool(project.Environment[ComposeIgnoreOrphans]) if create.ignoreOrphans && create.removeOrphans { - return fmt.Errorf("COMPOSE_IGNORE_ORPHANS and --remove-orphans cannot be combined") + return fmt.Errorf("%s and --remove-orphans cannot be combined", ComposeIgnoreOrphans) } return runUp(ctx, streams, backend, create, up, project, services) }),