]> git.immae.eu Git - github/fretlink/terraform-provider-statuscake.git/blob - vendor/github.com/fsouza/go-dockerclient/exec.go
provider: Ensured Go 1.11 in TravisCI and README
[github/fretlink/terraform-provider-statuscake.git] / vendor / github.com / fsouza / go-dockerclient / exec.go
1 // Copyright 2015 go-dockerclient authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5 package docker
6
7 import (
8 "encoding/json"
9 "fmt"
10 "io"
11 "net/http"
12 "net/url"
13 "strconv"
14 )
15
16 // Exec is the type representing a `docker exec` instance and containing the
17 // instance ID
18 type Exec struct {
19 ID string `json:"Id,omitempty" yaml:"Id,omitempty"`
20 }
21
22 // CreateExecOptions specify parameters to the CreateExecContainer function.
23 //
24 // See https://goo.gl/1KSIb7 for more details
25 type CreateExecOptions struct {
26 AttachStdin bool `json:"AttachStdin,omitempty" yaml:"AttachStdin,omitempty"`
27 AttachStdout bool `json:"AttachStdout,omitempty" yaml:"AttachStdout,omitempty"`
28 AttachStderr bool `json:"AttachStderr,omitempty" yaml:"AttachStderr,omitempty"`
29 Tty bool `json:"Tty,omitempty" yaml:"Tty,omitempty"`
30 Cmd []string `json:"Cmd,omitempty" yaml:"Cmd,omitempty"`
31 Container string `json:"Container,omitempty" yaml:"Container,omitempty"`
32 User string `json:"User,omitempty" yaml:"User,omitempty"`
33 }
34
35 // CreateExec sets up an exec instance in a running container `id`, returning the exec
36 // instance, or an error in case of failure.
37 //
38 // See https://goo.gl/1KSIb7 for more details
39 func (c *Client) CreateExec(opts CreateExecOptions) (*Exec, error) {
40 path := fmt.Sprintf("/containers/%s/exec", opts.Container)
41 resp, err := c.do("POST", path, doOptions{data: opts})
42 if err != nil {
43 if e, ok := err.(*Error); ok && e.Status == http.StatusNotFound {
44 return nil, &NoSuchContainer{ID: opts.Container}
45 }
46 return nil, err
47 }
48 defer resp.Body.Close()
49 var exec Exec
50 if err := json.NewDecoder(resp.Body).Decode(&exec); err != nil {
51 return nil, err
52 }
53
54 return &exec, nil
55 }
56
57 // StartExecOptions specify parameters to the StartExecContainer function.
58 //
59 // See https://goo.gl/iQCnto for more details
60 type StartExecOptions struct {
61 Detach bool `json:"Detach,omitempty" yaml:"Detach,omitempty"`
62
63 Tty bool `json:"Tty,omitempty" yaml:"Tty,omitempty"`
64
65 InputStream io.Reader `qs:"-"`
66 OutputStream io.Writer `qs:"-"`
67 ErrorStream io.Writer `qs:"-"`
68
69 // Use raw terminal? Usually true when the container contains a TTY.
70 RawTerminal bool `qs:"-"`
71
72 // If set, after a successful connect, a sentinel will be sent and then the
73 // client will block on receive before continuing.
74 //
75 // It must be an unbuffered channel. Using a buffered channel can lead
76 // to unexpected behavior.
77 Success chan struct{} `json:"-"`
78 }
79
80 // StartExec starts a previously set up exec instance id. If opts.Detach is
81 // true, it returns after starting the exec command. Otherwise, it sets up an
82 // interactive session with the exec command.
83 //
84 // See https://goo.gl/iQCnto for more details
85 func (c *Client) StartExec(id string, opts StartExecOptions) error {
86 cw, err := c.StartExecNonBlocking(id, opts)
87 if err != nil {
88 return err
89 }
90 if cw != nil {
91 return cw.Wait()
92 }
93 return nil
94 }
95
96 // StartExecNonBlocking starts a previously set up exec instance id. If opts.Detach is
97 // true, it returns after starting the exec command. Otherwise, it sets up an
98 // interactive session with the exec command.
99 //
100 // See https://goo.gl/iQCnto for more details
101 func (c *Client) StartExecNonBlocking(id string, opts StartExecOptions) (CloseWaiter, error) {
102 if id == "" {
103 return nil, &NoSuchExec{ID: id}
104 }
105
106 path := fmt.Sprintf("/exec/%s/start", id)
107
108 if opts.Detach {
109 resp, err := c.do("POST", path, doOptions{data: opts})
110 if err != nil {
111 if e, ok := err.(*Error); ok && e.Status == http.StatusNotFound {
112 return nil, &NoSuchExec{ID: id}
113 }
114 return nil, err
115 }
116 defer resp.Body.Close()
117 return nil, nil
118 }
119
120 return c.hijack("POST", path, hijackOptions{
121 success: opts.Success,
122 setRawTerminal: opts.RawTerminal,
123 in: opts.InputStream,
124 stdout: opts.OutputStream,
125 stderr: opts.ErrorStream,
126 data: opts,
127 })
128 }
129
130 // ResizeExecTTY resizes the tty session used by the exec command id. This API
131 // is valid only if Tty was specified as part of creating and starting the exec
132 // command.
133 //
134 // See https://goo.gl/e1JpsA for more details
135 func (c *Client) ResizeExecTTY(id string, height, width int) error {
136 params := make(url.Values)
137 params.Set("h", strconv.Itoa(height))
138 params.Set("w", strconv.Itoa(width))
139
140 path := fmt.Sprintf("/exec/%s/resize?%s", id, params.Encode())
141 resp, err := c.do("POST", path, doOptions{})
142 if err != nil {
143 return err
144 }
145 resp.Body.Close()
146 return nil
147 }
148
149 // ExecProcessConfig is a type describing the command associated to a Exec
150 // instance. It's used in the ExecInspect type.
151 type ExecProcessConfig struct {
152 Privileged bool `json:"privileged,omitempty" yaml:"privileged,omitempty"`
153 User string `json:"user,omitempty" yaml:"user,omitempty"`
154 Tty bool `json:"tty,omitempty" yaml:"tty,omitempty"`
155 EntryPoint string `json:"entrypoint,omitempty" yaml:"entrypoint,omitempty"`
156 Arguments []string `json:"arguments,omitempty" yaml:"arguments,omitempty"`
157 }
158
159 // ExecInspect is a type with details about a exec instance, including the
160 // exit code if the command has finished running. It's returned by a api
161 // call to /exec/(id)/json
162 //
163 // See https://goo.gl/gPtX9R for more details
164 type ExecInspect struct {
165 ID string `json:"ID,omitempty" yaml:"ID,omitempty"`
166 Running bool `json:"Running,omitempty" yaml:"Running,omitempty"`
167 ExitCode int `json:"ExitCode,omitempty" yaml:"ExitCode,omitempty"`
168 OpenStdin bool `json:"OpenStdin,omitempty" yaml:"OpenStdin,omitempty"`
169 OpenStderr bool `json:"OpenStderr,omitempty" yaml:"OpenStderr,omitempty"`
170 OpenStdout bool `json:"OpenStdout,omitempty" yaml:"OpenStdout,omitempty"`
171 ProcessConfig ExecProcessConfig `json:"ProcessConfig,omitempty" yaml:"ProcessConfig,omitempty"`
172 Container Container `json:"Container,omitempty" yaml:"Container,omitempty"`
173 }
174
175 // InspectExec returns low-level information about the exec command id.
176 //
177 // See https://goo.gl/gPtX9R for more details
178 func (c *Client) InspectExec(id string) (*ExecInspect, error) {
179 path := fmt.Sprintf("/exec/%s/json", id)
180 resp, err := c.do("GET", path, doOptions{})
181 if err != nil {
182 if e, ok := err.(*Error); ok && e.Status == http.StatusNotFound {
183 return nil, &NoSuchExec{ID: id}
184 }
185 return nil, err
186 }
187 defer resp.Body.Close()
188 var exec ExecInspect
189 if err := json.NewDecoder(resp.Body).Decode(&exec); err != nil {
190 return nil, err
191 }
192 return &exec, nil
193 }
194
195 // NoSuchExec is the error returned when a given exec instance does not exist.
196 type NoSuchExec struct {
197 ID string
198 }
199
200 func (err *NoSuchExec) Error() string {
201 return "No such exec instance: " + err.ID
202 }