Add ExecIDs to docker inspect
| ... | ... |
@@ -35,7 +35,7 @@ type execConfig struct {
|
| 35 | 35 |
|
| 36 | 36 |
type execStore struct {
|
| 37 | 37 |
s map[string]*execConfig |
| 38 |
- sync.Mutex |
|
| 38 |
+ sync.RWMutex |
|
| 39 | 39 |
} |
| 40 | 40 |
|
| 41 | 41 |
func newExecStore() *execStore {
|
| ... | ... |
@@ -49,9 +49,9 @@ func (e *execStore) Add(id string, execConfig *execConfig) {
|
| 49 | 49 |
} |
| 50 | 50 |
|
| 51 | 51 |
func (e *execStore) Get(id string) *execConfig {
|
| 52 |
- e.Lock() |
|
| 52 |
+ e.RLock() |
|
| 53 | 53 |
res := e.s[id] |
| 54 |
- e.Unlock() |
|
| 54 |
+ e.RUnlock() |
|
| 55 | 55 |
return res |
| 56 | 56 |
} |
| 57 | 57 |
|
| ... | ... |
@@ -61,6 +61,16 @@ func (e *execStore) Delete(id string) {
|
| 61 | 61 |
e.Unlock() |
| 62 | 62 |
} |
| 63 | 63 |
|
| 64 |
+func (e *execStore) List() []string {
|
|
| 65 |
+ var IDs []string |
|
| 66 |
+ e.RLock() |
|
| 67 |
+ for id := range e.s {
|
|
| 68 |
+ IDs = append(IDs, id) |
|
| 69 |
+ } |
|
| 70 |
+ e.RUnlock() |
|
| 71 |
+ return IDs |
|
| 72 |
+} |
|
| 73 |
+ |
|
| 64 | 74 |
func (execConfig *execConfig) Resize(h, w int) error {
|
| 65 | 75 |
return execConfig.ProcessConfig.Terminal.Resize(h, w) |
| 66 | 76 |
} |
| ... | ... |
@@ -249,6 +259,10 @@ func (d *Daemon) Exec(c *Container, execConfig *execConfig, pipes *execdriver.Pi |
| 249 | 249 |
return exitStatus, err |
| 250 | 250 |
} |
| 251 | 251 |
|
| 252 |
+func (container *Container) GetExecIDs() []string {
|
|
| 253 |
+ return container.execCommands.List() |
|
| 254 |
+} |
|
| 255 |
+ |
|
| 252 | 256 |
func (container *Container) Exec(execConfig *execConfig) error {
|
| 253 | 257 |
container.Lock() |
| 254 | 258 |
defer container.Unlock() |
| ... | ... |
@@ -50,6 +50,8 @@ func (daemon *Daemon) ContainerInspect(job *engine.Job) engine.Status {
|
| 50 | 50 |
out.SetJson("VolumesRW", container.VolumesRW)
|
| 51 | 51 |
out.SetJson("AppArmorProfile", container.AppArmorProfile)
|
| 52 | 52 |
|
| 53 |
+ out.SetList("ExecIDs", container.GetExecIDs())
|
|
| 54 |
+ |
|
| 53 | 55 |
if children, err := daemon.Children(container.Name); err == nil {
|
| 54 | 56 |
for linkAlias, child := range children {
|
| 55 | 57 |
container.hostConfig.Links = append(container.hostConfig.Links, fmt.Sprintf("%s:%s", child.Name, linkAlias))
|
| ... | ... |
@@ -51,6 +51,11 @@ You can still call an old version of the API using |
| 51 | 51 |
**New!** |
| 52 | 52 |
Docker client now hints potential proxies about connection hijacking using HTTP Upgrade headers. |
| 53 | 53 |
|
| 54 |
+`GET /containers/(id)/json` |
|
| 55 |
+ |
|
| 56 |
+**New!** |
|
| 57 |
+This endpoint now returns the list current execs associated with the container (`ExecIDs`). |
|
| 58 |
+ |
|
| 54 | 59 |
## v1.16 |
| 55 | 60 |
|
| 56 | 61 |
### Full Documentation |
| ... | ... |
@@ -310,6 +310,9 @@ Return low-level information on the container `id` |
| 310 | 310 |
"SysInitPath": "/home/kitty/go/src/github.com/docker/docker/bin/docker", |
| 311 | 311 |
"ResolvConfPath": "/etc/resolv.conf", |
| 312 | 312 |
"Volumes": {},
|
| 313 |
+ "ExecIDs": [ |
|
| 314 |
+ "15f211491dced6a353a2e0f37fe3f3692ee2370a4782418e9bf7052865c10fde" |
|
| 315 |
+ ], |
|
| 313 | 316 |
"HostConfig": {
|
| 314 | 317 |
"Binds": null, |
| 315 | 318 |
"ContainerIDFile": "", |
| ... | ... |
@@ -21,3 +21,38 @@ func TestInspectImage(t *testing.T) {
|
| 21 | 21 |
|
| 22 | 22 |
logDone("inspect - inspect an image")
|
| 23 | 23 |
} |
| 24 |
+ |
|
| 25 |
+func TestInspectExecID(t *testing.T) {
|
|
| 26 |
+ defer deleteAllContainers() |
|
| 27 |
+ |
|
| 28 |
+ out, exitCode, err := runCommandWithOutput(exec.Command(dockerBinary, "run", "-d", "busybox", "top")) |
|
| 29 |
+ if exitCode != 0 || err != nil {
|
|
| 30 |
+ t.Fatalf("failed to run container: %s, %v", out, err)
|
|
| 31 |
+ } |
|
| 32 |
+ id := strings.TrimSuffix(out, "\n") |
|
| 33 |
+ |
|
| 34 |
+ out, err = inspectField(id, "ExecIDs") |
|
| 35 |
+ if err != nil {
|
|
| 36 |
+ t.Fatalf("failed to inspect container: %s, %v", out, err)
|
|
| 37 |
+ } |
|
| 38 |
+ if out != "<no value>" {
|
|
| 39 |
+ t.Fatalf("ExecIDs should be empty, got: %s", out)
|
|
| 40 |
+ } |
|
| 41 |
+ |
|
| 42 |
+ exitCode, err = runCommand(exec.Command(dockerBinary, "exec", "-d", id, "ls", "/")) |
|
| 43 |
+ if exitCode != 0 || err != nil {
|
|
| 44 |
+ t.Fatalf("failed to exec in container: %s, %v", out, err)
|
|
| 45 |
+ } |
|
| 46 |
+ |
|
| 47 |
+ out, err = inspectField(id, "ExecIDs") |
|
| 48 |
+ if err != nil {
|
|
| 49 |
+ t.Fatalf("failed to inspect container: %s, %v", out, err)
|
|
| 50 |
+ } |
|
| 51 |
+ |
|
| 52 |
+ out = strings.TrimSuffix(out, "\n") |
|
| 53 |
+ if out == "[]" || out == "<no value>" {
|
|
| 54 |
+ t.Fatalf("ExecIDs should not be empty, got: %s", out)
|
|
| 55 |
+ } |
|
| 56 |
+ |
|
| 57 |
+ logDone("inspect - inspect a container with ExecIDs")
|
|
| 58 |
+} |