(p *ProjectOptions, dockerCli command.Cli, backendOptions *BackendOptions)
| 143 | } |
| 144 | |
| 145 | func runCommand(p *ProjectOptions, dockerCli command.Cli, backendOptions *BackendOptions) *cobra.Command { |
| 146 | options := runOptions{ |
| 147 | composeOptions: &composeOptions{ |
| 148 | ProjectOptions: p, |
| 149 | }, |
| 150 | capAdd: opts.NewListOpts(nil), |
| 151 | capDrop: opts.NewListOpts(nil), |
| 152 | } |
| 153 | createOpts := createOptions{} |
| 154 | buildOpts := buildOptions{ |
| 155 | ProjectOptions: p, |
| 156 | } |
| 157 | // We remove the attribute from the option struct and use a dedicated var, to limit confusion and avoid anyone to use options.tty. |
| 158 | // The tty flag is here for convenience and let user do "docker compose run -it" the same way as they use the "docker run" command. |
| 159 | var ttyFlag bool |
| 160 | |
| 161 | cmd := &cobra.Command{ |
| 162 | Use: "run [OPTIONS] SERVICE [COMMAND] [ARGS...]", |
| 163 | Short: "Run a one-off command on a service", |
| 164 | Args: cobra.MinimumNArgs(1), |
| 165 | PreRunE: AdaptCmd(func(ctx context.Context, cmd *cobra.Command, args []string) error { |
| 166 | options.Service = args[0] |
| 167 | if len(args) > 1 { |
| 168 | options.Command = args[1:] |
| 169 | } |
| 170 | if len(options.publish) > 0 && options.servicePorts { |
| 171 | return fmt.Errorf("--service-ports and --publish are incompatible") |
| 172 | } |
| 173 | if cmd.Flags().Changed("entrypoint") { |
| 174 | command, err := shellwords.Parse(options.entrypoint) |
| 175 | if err != nil { |
| 176 | return err |
| 177 | } |
| 178 | options.entrypointCmd = command |
| 179 | } |
| 180 | if cmd.Flags().Changed("tty") { |
| 181 | if cmd.Flags().Changed("no-tty") { |
| 182 | return fmt.Errorf("--tty and --no-tty can't be used together") |
| 183 | } else { |
| 184 | options.noTty = !ttyFlag |
| 185 | } |
| 186 | } else if !cmd.Flags().Changed("no-tty") && !cmd.Flags().Changed("interactive") && !dockerCli.In().IsTerminal() { |
| 187 | // while `docker run` requires explicit `-it` flags, Compose enables interactive mode and TTY by default |
| 188 | // but when compose is used from a script that has stdin piped from another command, we just can't |
| 189 | // Here, we detect we run "by default" (user didn't passed explicit flags) and disable TTY allocation if |
| 190 | // we don't have an actual terminal to attach to for interactive mode |
| 191 | options.noTty = true |
| 192 | } |
| 193 | |
| 194 | if options.quiet { |
| 195 | display.Mode = display.ModeQuiet |
| 196 | backendOptions.Add(compose.WithEventProcessor(display.Quiet())) |
| 197 | } |
| 198 | createOpts.pullChanged = cmd.Flags().Changed("pull") |
| 199 | return nil |
| 200 | }), |
| 201 | RunE: Adapt(func(ctx context.Context, args []string) error { |
| 202 | backend, err := compose.NewComposeService(dockerCli, backendOptions.Options...) |
no test coverage detected