github.com/containerd/nerdctl@v1.7.7/cmd/nerdctl/container_attach.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  	"github.com/containerd/containerd"
    21  	"github.com/containerd/nerdctl/pkg/api/types"
    22  	"github.com/containerd/nerdctl/pkg/clientutil"
    23  	"github.com/containerd/nerdctl/pkg/cmd/container"
    24  	"github.com/containerd/nerdctl/pkg/consoleutil"
    25  	"github.com/spf13/cobra"
    26  )
    27  
    28  func newAttachCommand() *cobra.Command {
    29  	const shortHelp = "Attach stdin, stdout, and stderr to a running container."
    30  	const longHelp = `Attach stdin, stdout, and stderr to a running container. For example:
    31  
    32  1. 'nerdctl run -it --name test busybox' to start a container with a pty
    33  2. 'ctrl-p ctrl-q' to detach from the container
    34  3. 'nerdctl attach test' to attach to the container
    35  
    36  Caveats:
    37  
    38  - Currently only one attach session is allowed. When the second session tries to attach, currently no error will be returned from nerdctl.
    39    However, since behind the scenes, there's only one FIFO for stdin, stdout, and stderr respectively,
    40    if there are multiple sessions, all the sessions will be reading from and writing to the same 3 FIFOs, which will result in mixed input and partial output.
    41  - Until dual logging (issue #1946) is implemented,
    42    a container that is spun up by either 'nerdctl run -d' or 'nerdctl start' (without '--attach') cannot be attached to.`
    43  
    44  	var attachCommand = &cobra.Command{
    45  		Use:               "attach [flags] CONTAINER",
    46  		Args:              cobra.ExactArgs(1),
    47  		Short:             shortHelp,
    48  		Long:              longHelp,
    49  		RunE:              containerAttachAction,
    50  		ValidArgsFunction: attachShellComplete,
    51  		SilenceUsage:      true,
    52  		SilenceErrors:     true,
    53  	}
    54  	attachCommand.Flags().String("detach-keys", consoleutil.DefaultDetachKeys, "Override the default detach keys")
    55  	return attachCommand
    56  }
    57  
    58  func processContainerAttachOptions(cmd *cobra.Command) (types.ContainerAttachOptions, error) {
    59  	globalOptions, err := processRootCmdFlags(cmd)
    60  	if err != nil {
    61  		return types.ContainerAttachOptions{}, err
    62  	}
    63  	detachKeys, err := cmd.Flags().GetString("detach-keys")
    64  	if err != nil {
    65  		return types.ContainerAttachOptions{}, err
    66  	}
    67  	return types.ContainerAttachOptions{
    68  		GOptions:   globalOptions,
    69  		Stdin:      cmd.InOrStdin(),
    70  		Stdout:     cmd.OutOrStdout(),
    71  		Stderr:     cmd.ErrOrStderr(),
    72  		DetachKeys: detachKeys,
    73  	}, nil
    74  }
    75  
    76  func containerAttachAction(cmd *cobra.Command, args []string) error {
    77  	options, err := processContainerAttachOptions(cmd)
    78  	if err != nil {
    79  		return err
    80  	}
    81  
    82  	client, ctx, cancel, err := clientutil.NewClient(cmd.Context(), options.GOptions.Namespace, options.GOptions.Address)
    83  	if err != nil {
    84  		return err
    85  	}
    86  	defer cancel()
    87  
    88  	return container.Attach(ctx, client, args[0], options)
    89  }
    90  
    91  func attachShellComplete(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
    92  	statusFilterFn := func(st containerd.ProcessStatus) bool {
    93  		return st == containerd.Running
    94  	}
    95  	return shellCompleteContainerNames(cmd, statusFilterFn)
    96  }