github.com/containerd/nerdctl@v1.7.7/cmd/nerdctl/compose_run.go (about)

     1  /*
     2     Copyright The containerd Authors.
     3  
     4     Licensed under the Apache License, Version 2.0 (the "License");
     5     you may not use this file except in compliance with the License.
     6     You may obtain a copy of the License at
     7  
     8         http://www.apache.org/licenses/LICENSE-2.0
     9  
    10     Unless required by applicable law or agreed to in writing, software
    11     distributed under the License is distributed on an "AS IS" BASIS,
    12     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13     See the License for the specific language governing permissions and
    14     limitations under the License.
    15  */
    16  
    17  package main
    18  
    19  import (
    20  	"errors"
    21  	"fmt"
    22  
    23  	"github.com/containerd/nerdctl/pkg/clientutil"
    24  	"github.com/containerd/nerdctl/pkg/cmd/compose"
    25  	"github.com/containerd/nerdctl/pkg/composer"
    26  	"github.com/spf13/cobra"
    27  )
    28  
    29  func newComposeRunCommand() *cobra.Command {
    30  	var composeRunCommand = &cobra.Command{
    31  		Use:                   "run [flags] SERVICE [COMMAND] [ARGS...]",
    32  		Short:                 "Run a one-off command on a service",
    33  		Args:                  cobra.MinimumNArgs(1),
    34  		RunE:                  composeRunAction,
    35  		SilenceUsage:          true,
    36  		SilenceErrors:         true,
    37  		DisableFlagsInUseLine: true,
    38  	}
    39  	composeRunCommand.Flags().SetInterspersed(false)
    40  	composeRunCommand.Flags().BoolP("detach", "d", false, "Detached mode: Run containers in the background")
    41  	composeRunCommand.Flags().Bool("no-build", false, "Don't build an image, even if it's missing.")
    42  	composeRunCommand.Flags().Bool("no-color", false, "Produce monochrome output")
    43  	composeRunCommand.Flags().Bool("no-log-prefix", false, "Don't print prefix in logs")
    44  	composeRunCommand.Flags().Bool("build", false, "Build images before starting containers.")
    45  	composeRunCommand.Flags().Bool("quiet-pull", false, "Pull without printing progress information")
    46  	composeRunCommand.Flags().Bool("remove-orphans", false, "Remove containers for services not defined in the Compose file.")
    47  
    48  	composeRunCommand.Flags().String("name", "", "Assign a name to the container")
    49  	composeRunCommand.Flags().Bool("no-deps", false, "Don't start dependencies")
    50  	// TODO: no-TTY flag
    51  	//       In docker-compose's documentation, no-TTY is automatically detected
    52  	//       But, it follows `-i` flag because currently `run` command needs `-it` simultaneously.
    53  	composeRunCommand.Flags().BoolP("interactive", "i", true, "Keep STDIN open even if not attached")
    54  	composeRunCommand.Flags().Bool("rm", false, "Automatically remove the container when it exits")
    55  	composeRunCommand.Flags().StringP("user", "u", "", "Username or UID (format: <name|uid>[:<group|gid>])")
    56  	composeRunCommand.Flags().StringArrayP("volume", "v", nil, "Bind mount a volume")
    57  	composeRunCommand.Flags().StringArray("entrypoint", nil, "Overwrite the default ENTRYPOINT of the image")
    58  	composeRunCommand.Flags().StringArrayP("env", "e", nil, "Set environment variables")
    59  	composeRunCommand.Flags().StringArrayP("label", "l", nil, "Set metadata on container")
    60  	composeRunCommand.Flags().StringP("workdir", "w", "", "Working directory inside the container")
    61  	// FIXME: `-p` conflicts with the `--project-name` in PersistentFlags of parent command `compose`
    62  	//        For docker compatibility, it should be fixed.
    63  	composeRunCommand.Flags().StringSlice("publish", nil, "Publish a container's port(s) to the host")
    64  	composeRunCommand.Flags().Bool("service-ports", false, "Run command with the service's ports enabled and mapped to the host")
    65  	// TODO: use-aliases
    66  
    67  	return composeRunCommand
    68  }
    69  
    70  func composeRunAction(cmd *cobra.Command, args []string) error {
    71  	globalOptions, err := processRootCmdFlags(cmd)
    72  	if err != nil {
    73  		return err
    74  	}
    75  	detach, err := cmd.Flags().GetBool("detach")
    76  	if err != nil {
    77  		return err
    78  	}
    79  	noBuild, err := cmd.Flags().GetBool("no-build")
    80  	if err != nil {
    81  		return err
    82  	}
    83  	noColor, err := cmd.Flags().GetBool("no-color")
    84  	if err != nil {
    85  		return err
    86  	}
    87  	noLogPrefix, err := cmd.Flags().GetBool("no-log-prefix")
    88  	if err != nil {
    89  		return err
    90  	}
    91  	build, err := cmd.Flags().GetBool("build")
    92  	if err != nil {
    93  		return err
    94  	}
    95  	if build && noBuild {
    96  		return errors.New("--build and --no-build can not be combined")
    97  	}
    98  	quietPull, err := cmd.Flags().GetBool("quiet-pull")
    99  	if err != nil {
   100  		return err
   101  	}
   102  	removeOrphans, err := cmd.Flags().GetBool("remove-orphans")
   103  	if err != nil {
   104  		return err
   105  	}
   106  
   107  	name, err := cmd.Flags().GetString("name")
   108  	if err != nil {
   109  		return err
   110  	}
   111  	nodeps, err := cmd.Flags().GetBool("no-deps")
   112  	if err != nil {
   113  		return err
   114  	}
   115  
   116  	interactive, err := cmd.Flags().GetBool("interactive")
   117  	if err != nil {
   118  		return err
   119  	}
   120  	// FIXME : https://github.com/containerd/nerdctl/blob/v0.22.2/cmd/nerdctl/run.go#L100
   121  	tty := interactive
   122  	rm, err := cmd.Flags().GetBool("rm")
   123  	if err != nil {
   124  		return err
   125  	}
   126  	user, err := cmd.Flags().GetString("user")
   127  	if err != nil {
   128  		return err
   129  	}
   130  	volume, err := cmd.Flags().GetStringArray("volume")
   131  	if err != nil {
   132  		return err
   133  	}
   134  	entrypoint, err := cmd.Flags().GetStringArray("entrypoint")
   135  	if err != nil {
   136  		return err
   137  	}
   138  	env, err := cmd.Flags().GetStringArray("env")
   139  	if err != nil {
   140  		return err
   141  	}
   142  	label, err := cmd.Flags().GetStringArray("label")
   143  	if err != nil {
   144  		return err
   145  	}
   146  	workdir, err := cmd.Flags().GetString("workdir")
   147  	if err != nil {
   148  		return err
   149  	}
   150  	publish, err := cmd.Flags().GetStringSlice("publish")
   151  	if err != nil {
   152  		return err
   153  	}
   154  	servicePorts, err := cmd.Flags().GetBool("service-ports")
   155  	if err != nil {
   156  		return err
   157  	}
   158  
   159  	if servicePorts && publish != nil && len(publish) > 0 {
   160  		return fmt.Errorf("--service-ports and --publish(-p) cannot exist simultaneously")
   161  	}
   162  	// https://github.com/containerd/nerdctl/blob/v0.22.2/cmd/nerdctl/run.go#L475
   163  	if interactive && detach {
   164  		return errors.New("currently flag -i and -d cannot be specified together (FIXME)")
   165  	}
   166  
   167  	// https://github.com/containerd/nerdctl/blob/v0.22.2/cmd/nerdctl/run.go#L479
   168  	if tty && detach {
   169  		return errors.New("currently flag -t and -d cannot be specified together (FIXME)")
   170  	}
   171  
   172  	client, ctx, cancel, err := clientutil.NewClient(cmd.Context(), globalOptions.Namespace, globalOptions.Address)
   173  	if err != nil {
   174  		return err
   175  	}
   176  	defer cancel()
   177  	options, err := getComposeOptions(cmd, globalOptions.DebugFull, globalOptions.Experimental)
   178  	if err != nil {
   179  		return err
   180  	}
   181  	c, err := compose.New(client, globalOptions, options, cmd.OutOrStdout(), cmd.ErrOrStderr())
   182  	if err != nil {
   183  		return err
   184  	}
   185  
   186  	ro := composer.RunOptions{
   187  		Detach:        detach,
   188  		NoBuild:       noBuild,
   189  		NoColor:       noColor,
   190  		NoLogPrefix:   noLogPrefix,
   191  		ForceBuild:    build,
   192  		QuietPull:     quietPull,
   193  		RemoveOrphans: removeOrphans,
   194  
   195  		ServiceName: args[0],
   196  		Args:        args[1:],
   197  
   198  		Name:         name,
   199  		NoDeps:       nodeps,
   200  		Tty:          tty,
   201  		Interactive:  interactive,
   202  		Rm:           rm,
   203  		User:         user,
   204  		Volume:       volume,
   205  		Entrypoint:   entrypoint,
   206  		Env:          env,
   207  		Label:        label,
   208  		WorkDir:      workdir,
   209  		ServicePorts: servicePorts,
   210  		Publish:      publish,
   211  	}
   212  
   213  	return c.Run(ctx, ro)
   214  }