podman

Форк
0
224 строки · 8.5 Кб
1
// Copyright 2014 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
	"context"
9
	"encoding/json"
10
	"errors"
11
	"fmt"
12
	"io"
13
	"net/http"
14
	"net/url"
15
	"strconv"
16
)
17

18
// Exec is the type representing a `docker exec` instance and containing the
19
// instance ID
20
type Exec struct {
21
	ID string `json:"Id,omitempty" yaml:"Id,omitempty"`
22
}
23

24
// CreateExecOptions specify parameters to the CreateExecContainer function.
25
//
26
// See https://goo.gl/60TeBP for more details
27
type CreateExecOptions struct {
28
	Env          []string        `json:"Env,omitempty" yaml:"Env,omitempty" toml:"Env,omitempty"`
29
	Cmd          []string        `json:"Cmd,omitempty" yaml:"Cmd,omitempty" toml:"Cmd,omitempty"`
30
	Container    string          `json:"Container,omitempty" yaml:"Container,omitempty" toml:"Container,omitempty"`
31
	User         string          `json:"User,omitempty" yaml:"User,omitempty" toml:"User,omitempty"`
32
	WorkingDir   string          `json:"WorkingDir,omitempty" yaml:"WorkingDir,omitempty" toml:"WorkingDir,omitempty"`
33
	DetachKeys   string          `json:"DetachKeys,omitempty" yaml:"DetachKeys,omitempty" toml:"DetachKeys,omitempty"`
34
	Context      context.Context `json:"-"`
35
	AttachStdin  bool            `json:"AttachStdin,omitempty" yaml:"AttachStdin,omitempty" toml:"AttachStdin,omitempty"`
36
	AttachStdout bool            `json:"AttachStdout,omitempty" yaml:"AttachStdout,omitempty" toml:"AttachStdout,omitempty"`
37
	AttachStderr bool            `json:"AttachStderr,omitempty" yaml:"AttachStderr,omitempty" toml:"AttachStderr,omitempty"`
38
	Tty          bool            `json:"Tty,omitempty" yaml:"Tty,omitempty" toml:"Tty,omitempty"`
39
	Privileged   bool            `json:"Privileged,omitempty" yaml:"Privileged,omitempty" toml:"Privileged,omitempty"`
40
}
41

42
// CreateExec sets up an exec instance in a running container `id`, returning the exec
43
// instance, or an error in case of failure.
44
//
45
// See https://goo.gl/60TeBP for more details
46
func (c *Client) CreateExec(opts CreateExecOptions) (*Exec, error) {
47
	if c.serverAPIVersion == nil {
48
		c.checkAPIVersion()
49
	}
50
	if len(opts.Env) > 0 && c.serverAPIVersion.LessThan(apiVersion125) {
51
		return nil, errors.New("exec configuration Env is only supported in API#1.25 and above")
52
	}
53
	if len(opts.WorkingDir) > 0 && c.serverAPIVersion.LessThan(apiVersion135) {
54
		return nil, errors.New("exec configuration WorkingDir is only supported in API#1.35 and above")
55
	}
56
	path := fmt.Sprintf("/containers/%s/exec", opts.Container)
57
	resp, err := c.do(http.MethodPost, path, doOptions{data: opts, context: opts.Context})
58
	if err != nil {
59
		var e *Error
60
		if errors.As(err, &e) && e.Status == http.StatusNotFound {
61
			return nil, &NoSuchContainer{ID: opts.Container}
62
		}
63
		return nil, err
64
	}
65
	defer resp.Body.Close()
66
	var exec Exec
67
	if err := json.NewDecoder(resp.Body).Decode(&exec); err != nil {
68
		return nil, err
69
	}
70

71
	return &exec, nil
72
}
73

74
// StartExecOptions specify parameters to the StartExecContainer function.
75
//
76
// See https://goo.gl/1EeDWi for more details
77
type StartExecOptions struct {
78
	InputStream  io.Reader `qs:"-"`
79
	OutputStream io.Writer `qs:"-"`
80
	ErrorStream  io.Writer `qs:"-"`
81

82
	Detach bool `json:"Detach,omitempty" yaml:"Detach,omitempty" toml:"Detach,omitempty"`
83
	Tty    bool `json:"Tty,omitempty" yaml:"Tty,omitempty" toml:"Tty,omitempty"`
84

85
	// Use raw terminal? Usually true when the container contains a TTY.
86
	RawTerminal bool `qs:"-"`
87

88
	// If set, after a successful connect, a sentinel will be sent and then the
89
	// client will block on receive before continuing.
90
	//
91
	// It must be an unbuffered channel. Using a buffered channel can lead
92
	// to unexpected behavior.
93
	Success chan struct{} `json:"-"`
94

95
	Context context.Context `json:"-"`
96
}
97

98
// StartExec starts a previously set up exec instance id. If opts.Detach is
99
// true, it returns after starting the exec command. Otherwise, it sets up an
100
// interactive session with the exec command.
101
//
102
// See https://goo.gl/1EeDWi for more details
103
func (c *Client) StartExec(id string, opts StartExecOptions) error {
104
	cw, err := c.StartExecNonBlocking(id, opts)
105
	if err != nil {
106
		return err
107
	}
108
	if cw != nil {
109
		return cw.Wait()
110
	}
111
	return nil
112
}
113

114
// StartExecNonBlocking starts a previously set up exec instance id. If opts.Detach is
115
// true, it returns after starting the exec command. Otherwise, it sets up an
116
// interactive session with the exec command.
117
//
118
// See https://goo.gl/1EeDWi for more details
119
func (c *Client) StartExecNonBlocking(id string, opts StartExecOptions) (CloseWaiter, error) {
120
	if id == "" {
121
		return nil, &NoSuchExec{ID: id}
122
	}
123

124
	path := fmt.Sprintf("/exec/%s/start", id)
125

126
	if opts.Detach {
127
		resp, err := c.do(http.MethodPost, path, doOptions{data: opts, context: opts.Context})
128
		if err != nil {
129
			var e *Error
130
			if errors.As(err, &e) && e.Status == http.StatusNotFound {
131
				return nil, &NoSuchExec{ID: id}
132
			}
133
			return nil, err
134
		}
135
		defer resp.Body.Close()
136
		return nil, nil
137
	}
138

139
	return c.hijack(http.MethodPost, path, hijackOptions{
140
		success:        opts.Success,
141
		setRawTerminal: opts.RawTerminal,
142
		in:             opts.InputStream,
143
		stdout:         opts.OutputStream,
144
		stderr:         opts.ErrorStream,
145
		data:           opts,
146
	})
147
}
148

149
// ResizeExecTTY resizes the tty session used by the exec command id. This API
150
// is valid only if Tty was specified as part of creating and starting the exec
151
// command.
152
//
153
// See https://goo.gl/Mo5bxx for more details
154
func (c *Client) ResizeExecTTY(id string, height, width int) error {
155
	params := make(url.Values)
156
	params.Set("h", strconv.Itoa(height))
157
	params.Set("w", strconv.Itoa(width))
158

159
	path := fmt.Sprintf("/exec/%s/resize?%s", id, params.Encode())
160
	resp, err := c.do(http.MethodPost, path, doOptions{})
161
	if err != nil {
162
		return err
163
	}
164
	resp.Body.Close()
165
	return nil
166
}
167

168
// ExecProcessConfig is a type describing the command associated to a Exec
169
// instance. It's used in the ExecInspect type.
170
type ExecProcessConfig struct {
171
	User       string   `json:"user,omitempty" yaml:"user,omitempty" toml:"user,omitempty"`
172
	Privileged bool     `json:"privileged,omitempty" yaml:"privileged,omitempty" toml:"privileged,omitempty"`
173
	Tty        bool     `json:"tty,omitempty" yaml:"tty,omitempty" toml:"tty,omitempty"`
174
	EntryPoint string   `json:"entrypoint,omitempty" yaml:"entrypoint,omitempty" toml:"entrypoint,omitempty"`
175
	Arguments  []string `json:"arguments,omitempty" yaml:"arguments,omitempty" toml:"arguments,omitempty"`
176
}
177

178
// ExecInspect is a type with details about a exec instance, including the
179
// exit code if the command has finished running. It's returned by a api
180
// call to /exec/(id)/json
181
//
182
// See https://goo.gl/ctMUiW for more details
183
type ExecInspect struct {
184
	ID            string            `json:"ID,omitempty" yaml:"ID,omitempty" toml:"ID,omitempty"`
185
	ExitCode      int               `json:"ExitCode,omitempty" yaml:"ExitCode,omitempty" toml:"ExitCode,omitempty"`
186
	ProcessConfig ExecProcessConfig `json:"ProcessConfig,omitempty" yaml:"ProcessConfig,omitempty" toml:"ProcessConfig,omitempty"`
187
	ContainerID   string            `json:"ContainerID,omitempty" yaml:"ContainerID,omitempty" toml:"ContainerID,omitempty"`
188
	DetachKeys    string            `json:"DetachKeys,omitempty" yaml:"DetachKeys,omitempty" toml:"DetachKeys,omitempty"`
189
	Running       bool              `json:"Running,omitempty" yaml:"Running,omitempty" toml:"Running,omitempty"`
190
	OpenStdin     bool              `json:"OpenStdin,omitempty" yaml:"OpenStdin,omitempty" toml:"OpenStdin,omitempty"`
191
	OpenStderr    bool              `json:"OpenStderr,omitempty" yaml:"OpenStderr,omitempty" toml:"OpenStderr,omitempty"`
192
	OpenStdout    bool              `json:"OpenStdout,omitempty" yaml:"OpenStdout,omitempty" toml:"OpenStdout,omitempty"`
193
	CanRemove     bool              `json:"CanRemove,omitempty" yaml:"CanRemove,omitempty" toml:"CanRemove,omitempty"`
194
}
195

196
// InspectExec returns low-level information about the exec command id.
197
//
198
// See https://goo.gl/ctMUiW for more details
199
func (c *Client) InspectExec(id string) (*ExecInspect, error) {
200
	path := fmt.Sprintf("/exec/%s/json", id)
201
	resp, err := c.do(http.MethodGet, path, doOptions{})
202
	if err != nil {
203
		var e *Error
204
		if errors.As(err, &e) && e.Status == http.StatusNotFound {
205
			return nil, &NoSuchExec{ID: id}
206
		}
207
		return nil, err
208
	}
209
	defer resp.Body.Close()
210
	var exec ExecInspect
211
	if err := json.NewDecoder(resp.Body).Decode(&exec); err != nil {
212
		return nil, err
213
	}
214
	return &exec, nil
215
}
216

217
// NoSuchExec is the error returned when a given exec instance does not exist.
218
type NoSuchExec struct {
219
	ID string
220
}
221

222
func (err *NoSuchExec) Error() string {
223
	return "No such exec instance: " + err.ID
224
}
225

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.