forked from casualjim/go-dockerclient
-
Notifications
You must be signed in to change notification settings - Fork 0
/
misc.go
160 lines (145 loc) · 3.8 KB
/
misc.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
// Copyright 2014 go-dockerclient authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package docker
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net"
"os"
"strings"
"github.com/docker/docker/pkg/promise"
)
// Version returns version information about the docker server.
//
// See http://goo.gl/BOZrF5 for more details.
func (c *Client) Version() (*Env, error) {
body, _, err := c.do("GET", "/version", nil, false)
if err != nil {
return nil, err
}
var env Env
if err := env.Decode(bytes.NewReader(body)); err != nil {
return nil, err
}
return &env, nil
}
// Info returns system-wide information about the Docker server.
//
// See http://goo.gl/wmqZsW for more details.
func (c *Client) Info() (*Env, error) {
body, _, err := c.do("GET", "/info", nil, false)
if err != nil {
return nil, err
}
var info Env
err = info.Decode(bytes.NewReader(body))
if err != nil {
return nil, err
}
return &info, nil
}
// ExecOptions present the set of options available for pulling an image
// from a registry.
//
// See http://docs.docker.com/reference/api/docker_remote_api_v1.15/#exec-create for more details.
type ExecOptions struct {
User string
Privileged bool
AttachStdin bool
AttachStdout bool
AttachStderr bool
Tty bool
Command []string `json:"Cmd"`
Container string
OutputStream io.Writer `json:"-"`
ErrorStream io.Writer `json:"-"`
InputStream io.Reader `json:"-"`
Dialer func(string, string) (net.Conn, error) `json:"-"`
}
func (c *Client) Exec(opts ExecOptions) error {
if opts.Container == "" {
return &NoSuchContainer{ID: opts.Container}
}
name := opts.Container
path := "/containers/" + name + "/exec"
body, _, err := c.do("POST", path, opts, false)
if err != nil {
return err
}
id := struct{ Id string }{}
err = json.Unmarshal(body, &id)
if err != nil {
return err
}
if id.Id == "" {
return fmt.Errorf("Couldn't get an operation id for the exec command")
}
var (
hijacked = make(chan io.Closer)
errCh chan error
)
// Block the return until the chan gets closed
defer func() {
if _, ok := <-hijacked; ok {
fmt.Println("Hijack did not finish (chan still open)")
}
}()
doPath := "/exec/" + id.Id + "/start"
errCh = promise.Go(func() error {
stderr := opts.ErrorStream
if opts.Tty {
stderr = opts.OutputStream
}
return c.hijack2("POST", doPath, opts.Tty, opts.Dialer, opts.InputStream, opts.OutputStream, stderr, hijacked, opts)
})
select {
case closer := <-hijacked:
if closer != nil {
defer closer.Close()
}
case err := <-errCh:
if err != nil {
return err
}
}
var (
isTerminalIn, isTerminalOut bool
outFd uintptr
)
if _, ok := opts.InputStream.(*os.File); ok {
isTerminalIn = true
}
if file, ok := opts.OutputStream.(*os.File); ok {
isTerminalOut = true
outFd = file.Fd()
}
if opts.Tty && isTerminalIn {
if err := c.MonitorTtySize(id.Id, true, isTerminalOut, outFd); err != nil {
fmt.Printf("Error monitoring TTY size: %s\n", err)
}
}
if err := <-errCh; err != nil {
return err
}
return nil
}
// ParseRepositoryTag gets the name of the repository and returns it splitted
// in two parts: the repository and the tag.
//
// Some examples:
//
// localhost.localdomain:5000/samalba/hipache:latest -> localhost.localdomain:5000/samalba/hipache, latest
// localhost.localdomain:5000/samalba/hipache -> localhost.localdomain:5000/samalba/hipache, ""
func ParseRepositoryTag(repoTag string) (repository string, tag string) {
n := strings.LastIndex(repoTag, ":")
if n < 0 {
return repoTag, ""
}
if tag := repoTag[n+1:]; !strings.Contains(tag, "/") {
return repoTag[:n], tag
}
return repoTag, ""
}