@@ -17,12 +17,13 @@ import (
1717 "github.com/spf13/cobra"
1818)
1919
20- type attachOptions struct {
21- noStdin bool
22- proxy bool
23- detachKeys string
20+ // AttachOptions group options for `attach` command
21+ type AttachOptions struct {
22+ NoStdin bool
23+ Proxy bool
24+ DetachKeys string
2425
25- container string
26+ Container string
2627}
2728
2829func inspectContainerAndCheckState (ctx context.Context , cli client.APIClient , args string ) (* types.ContainerJSON , error ) {
@@ -45,15 +46,15 @@ func inspectContainerAndCheckState(ctx context.Context, cli client.APIClient, ar
4546
4647// NewAttachCommand creates a new cobra.Command for `docker attach`
4748func NewAttachCommand (dockerCli command.Cli ) * cobra.Command {
48- var opts attachOptions
49+ var opts AttachOptions
4950
5051 cmd := & cobra.Command {
5152 Use : "attach [OPTIONS] CONTAINER" ,
5253 Short : "Attach local standard input, output, and error streams to a running container" ,
5354 Args : cli .ExactArgs (1 ),
5455 RunE : func (cmd * cobra.Command , args []string ) error {
55- opts .container = args [0 ]
56- return runAttach (dockerCli , & opts )
56+ opts .Container = args [0 ]
57+ return RunAttach (dockerCli , & opts )
5758 },
5859 Annotations : map [string ]string {
5960 "aliases" : "docker container attach, docker attach" ,
@@ -64,36 +65,41 @@ func NewAttachCommand(dockerCli command.Cli) *cobra.Command {
6465 }
6566
6667 flags := cmd .Flags ()
67- flags .BoolVar (& opts .noStdin , "no-stdin" , false , "Do not attach STDIN" )
68- flags .BoolVar (& opts .proxy , "sig-proxy" , true , "Proxy all received signals to the process" )
69- flags .StringVar (& opts .detachKeys , "detach-keys" , "" , "Override the key sequence for detaching a container" )
68+ flags .BoolVar (& opts .NoStdin , "no-stdin" , false , "Do not attach STDIN" )
69+ flags .BoolVar (& opts .Proxy , "sig-proxy" , true , "Proxy all received signals to the process" )
70+ flags .StringVar (& opts .DetachKeys , "detach-keys" , "" , "Override the key sequence for detaching a container" )
7071 return cmd
7172}
7273
73- func runAttach (dockerCli command.Cli , opts * attachOptions ) error {
74- ctx := context .Background ()
74+ // RunAttach executes an `attach` command
75+ func RunAttach (dockerCli command.Cli , opts * AttachOptions ) error {
76+ return RunAttachWithContext (context .Background (), dockerCli , opts )
77+ }
78+
79+ // RunAttachWithContext executes an `attach` command
80+ func RunAttachWithContext (ctx context.Context , dockerCli command.Cli , opts * AttachOptions ) error {
7581 apiClient := dockerCli .Client ()
7682
7783 // request channel to wait for client
78- resultC , errC := apiClient .ContainerWait (ctx , opts .container , "" )
84+ resultC , errC := apiClient .ContainerWait (ctx , opts .Container , "" )
7985
80- c , err := inspectContainerAndCheckState (ctx , apiClient , opts .container )
86+ c , err := inspectContainerAndCheckState (ctx , apiClient , opts .Container )
8187 if err != nil {
8288 return err
8389 }
8490
85- if err := dockerCli .In ().CheckTty (! opts .noStdin , c .Config .Tty ); err != nil {
91+ if err := dockerCli .In ().CheckTty (! opts .NoStdin , c .Config .Tty ); err != nil {
8692 return err
8793 }
8894
8995 detachKeys := dockerCli .ConfigFile ().DetachKeys
90- if opts .detachKeys != "" {
91- detachKeys = opts .detachKeys
96+ if opts .DetachKeys != "" {
97+ detachKeys = opts .DetachKeys
9298 }
9399
94100 options := container.AttachOptions {
95101 Stream : true ,
96- Stdin : ! opts .noStdin && c .Config .OpenStdin ,
102+ Stdin : ! opts .NoStdin && c .Config .OpenStdin ,
97103 Stdout : true ,
98104 Stderr : true ,
99105 DetachKeys : detachKeys ,
@@ -104,13 +110,13 @@ func runAttach(dockerCli command.Cli, opts *attachOptions) error {
104110 in = dockerCli .In ()
105111 }
106112
107- if opts .proxy && ! c .Config .Tty {
113+ if opts .Proxy && ! c .Config .Tty {
108114 sigc := notifyAllSignals ()
109- go ForwardAllSignals (ctx , dockerCli , opts .container , sigc )
115+ go ForwardAllSignals (ctx , dockerCli , opts .Container , sigc )
110116 defer signal .StopCatch (sigc )
111117 }
112118
113- resp , errAttach := apiClient .ContainerAttach (ctx , opts .container , options )
119+ resp , errAttach := apiClient .ContainerAttach (ctx , opts .Container , options )
114120 if errAttach != nil {
115121 return errAttach
116122 }
@@ -124,13 +130,13 @@ func runAttach(dockerCli command.Cli, opts *attachOptions) error {
124130 // the container and not exit.
125131 //
126132 // Recheck the container's state to avoid attach block.
127- _ , err = inspectContainerAndCheckState (ctx , apiClient , opts .container )
133+ _ , err = inspectContainerAndCheckState (ctx , apiClient , opts .Container )
128134 if err != nil {
129135 return err
130136 }
131137
132138 if c .Config .Tty && dockerCli .Out ().IsTerminal () {
133- resizeTTY (ctx , dockerCli , opts .container )
139+ resizeTTY (ctx , dockerCli , opts .Container )
134140 }
135141
136142 streamer := hijackedIOStreamer {
0 commit comments