Skip to content

Commit 849563d

Browse files
authored
Merge pull request #216 from mxpv/logging
Allow stdio redirection inside VM
2 parents caa5ff0 + 832df2d commit 849563d

File tree

6 files changed

+222
-96
lines changed

6 files changed

+222
-96
lines changed

agent/service.go

Lines changed: 68 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -162,41 +162,48 @@ func (ts *TaskService) Create(requestCtx context.Context, req *taskAPI.CreateTas
162162
req.Bundle = bundleDir.RootPath()
163163
req.Rootfs = nil
164164

165-
// Override the incoming stdio FIFOs, which have paths from the host that we can't use
166-
fifoSet, err := cio.NewFIFOSetInDir(bundleDir.RootPath(), req.ID, req.Terminal)
167-
if err != nil {
168-
logger.WithError(err).Error("failed opening stdio FIFOs")
169-
return nil, errors.Wrap(err, "failed to open stdio FIFOs")
170-
}
165+
var ioConnectorSet vm.IOProxy
171166

172-
var stdinConnectorPair *vm.IOConnectorPair
173-
if req.Stdin != "" {
174-
req.Stdin = fifoSet.Stdin
175-
stdinConnectorPair = &vm.IOConnectorPair{
176-
ReadConnector: vm.VSockAcceptConnector(extraData.StdinPort),
177-
WriteConnector: vm.FIFOConnector(fifoSet.Stdin),
167+
if vm.IsAgentOnlyIO(req.Stdout, logger) {
168+
ioConnectorSet = vm.NewNullIOProxy()
169+
} else {
170+
// Override the incoming stdio FIFOs, which have paths from the host that we can't use
171+
fifoSet, err := cio.NewFIFOSetInDir(bundleDir.RootPath(), req.ID, req.Terminal)
172+
if err != nil {
173+
logger.WithError(err).Error("failed opening stdio FIFOs")
174+
return nil, errors.Wrap(err, "failed to open stdio FIFOs")
178175
}
179-
}
180176

181-
var stdoutConnectorPair *vm.IOConnectorPair
182-
if req.Stdout != "" {
183-
req.Stdout = fifoSet.Stdout
184-
stdoutConnectorPair = &vm.IOConnectorPair{
185-
ReadConnector: vm.FIFOConnector(fifoSet.Stdout),
186-
WriteConnector: vm.VSockAcceptConnector(extraData.StdoutPort),
177+
var stdinConnectorPair *vm.IOConnectorPair
178+
if req.Stdin != "" {
179+
req.Stdin = fifoSet.Stdin
180+
stdinConnectorPair = &vm.IOConnectorPair{
181+
ReadConnector: vm.VSockAcceptConnector(extraData.StdinPort),
182+
WriteConnector: vm.FIFOConnector(fifoSet.Stdin),
183+
}
187184
}
188-
}
189185

190-
var stderrConnectorPair *vm.IOConnectorPair
191-
if req.Stderr != "" {
192-
req.Stderr = fifoSet.Stderr
193-
stderrConnectorPair = &vm.IOConnectorPair{
194-
ReadConnector: vm.FIFOConnector(fifoSet.Stderr),
195-
WriteConnector: vm.VSockAcceptConnector(extraData.StderrPort),
186+
var stdoutConnectorPair *vm.IOConnectorPair
187+
if req.Stdout != "" {
188+
req.Stdout = fifoSet.Stdout
189+
stdoutConnectorPair = &vm.IOConnectorPair{
190+
ReadConnector: vm.FIFOConnector(fifoSet.Stdout),
191+
WriteConnector: vm.VSockAcceptConnector(extraData.StdoutPort),
192+
}
196193
}
194+
195+
var stderrConnectorPair *vm.IOConnectorPair
196+
if req.Stderr != "" {
197+
req.Stderr = fifoSet.Stderr
198+
stderrConnectorPair = &vm.IOConnectorPair{
199+
ReadConnector: vm.FIFOConnector(fifoSet.Stderr),
200+
WriteConnector: vm.VSockAcceptConnector(extraData.StderrPort),
201+
}
202+
}
203+
204+
ioConnectorSet = vm.NewIOConnectorProxy(stdinConnectorPair, stdoutConnectorPair, stderrConnectorPair)
197205
}
198206

199-
ioConnectorSet := vm.NewIOConnectorProxy(stdinConnectorPair, stdoutConnectorPair, stderrConnectorPair)
200207
resp, err := ts.taskManager.CreateTask(requestCtx, req, ts.runcService, ioConnectorSet)
201208
if err != nil {
202209
return nil, errors.Wrap(err, "failed to create runc shim for task")
@@ -349,41 +356,48 @@ func (ts *TaskService) Exec(requestCtx context.Context, req *taskAPI.ExecProcess
349356

350357
bundleDir := bundle.Dir(filepath.Join(containerRootDir, req.ID))
351358

352-
// Override the incoming stdio FIFOs, which have paths from the host that we can't use
353-
fifoSet, err := cio.NewFIFOSetInDir(bundleDir.RootPath(), req.ExecID, req.Terminal)
354-
if err != nil {
355-
logger.WithError(err).Error("failed opening stdio FIFOs")
356-
return nil, errors.Wrap(err, "failed to open stdio FIFOs")
357-
}
359+
var ioConnectorSet vm.IOProxy
358360

359-
var stdinConnectorPair *vm.IOConnectorPair
360-
if req.Stdin != "" {
361-
req.Stdin = fifoSet.Stdin
362-
stdinConnectorPair = &vm.IOConnectorPair{
363-
ReadConnector: vm.VSockAcceptConnector(extraData.StdinPort),
364-
WriteConnector: vm.FIFOConnector(fifoSet.Stdin),
361+
if vm.IsAgentOnlyIO(req.Stdout, logger) {
362+
ioConnectorSet = vm.NewNullIOProxy()
363+
} else {
364+
// Override the incoming stdio FIFOs, which have paths from the host that we can't use
365+
fifoSet, err := cio.NewFIFOSetInDir(bundleDir.RootPath(), req.ExecID, req.Terminal)
366+
if err != nil {
367+
logger.WithError(err).Error("failed opening stdio FIFOs")
368+
return nil, errors.Wrap(err, "failed to open stdio FIFOs")
365369
}
366-
}
367370

368-
var stdoutConnectorPair *vm.IOConnectorPair
369-
if req.Stdout != "" {
370-
req.Stdout = fifoSet.Stdout
371-
stdoutConnectorPair = &vm.IOConnectorPair{
372-
ReadConnector: vm.FIFOConnector(fifoSet.Stdout),
373-
WriteConnector: vm.VSockAcceptConnector(extraData.StdoutPort),
371+
var stdinConnectorPair *vm.IOConnectorPair
372+
if req.Stdin != "" {
373+
req.Stdin = fifoSet.Stdin
374+
stdinConnectorPair = &vm.IOConnectorPair{
375+
ReadConnector: vm.VSockAcceptConnector(extraData.StdinPort),
376+
WriteConnector: vm.FIFOConnector(fifoSet.Stdin),
377+
}
374378
}
375-
}
376379

377-
var stderrConnectorPair *vm.IOConnectorPair
378-
if req.Stderr != "" {
379-
req.Stderr = fifoSet.Stderr
380-
stderrConnectorPair = &vm.IOConnectorPair{
381-
ReadConnector: vm.FIFOConnector(fifoSet.Stderr),
382-
WriteConnector: vm.VSockAcceptConnector(extraData.StderrPort),
380+
var stdoutConnectorPair *vm.IOConnectorPair
381+
if req.Stdout != "" {
382+
req.Stdout = fifoSet.Stdout
383+
stdoutConnectorPair = &vm.IOConnectorPair{
384+
ReadConnector: vm.FIFOConnector(fifoSet.Stdout),
385+
WriteConnector: vm.VSockAcceptConnector(extraData.StdoutPort),
386+
}
383387
}
388+
389+
var stderrConnectorPair *vm.IOConnectorPair
390+
if req.Stderr != "" {
391+
req.Stderr = fifoSet.Stderr
392+
stderrConnectorPair = &vm.IOConnectorPair{
393+
ReadConnector: vm.FIFOConnector(fifoSet.Stderr),
394+
WriteConnector: vm.VSockAcceptConnector(extraData.StderrPort),
395+
}
396+
}
397+
398+
ioConnectorSet = vm.NewIOConnectorProxy(stdinConnectorPair, stdoutConnectorPair, stderrConnectorPair)
384399
}
385400

386-
ioConnectorSet := vm.NewIOConnectorProxy(stdinConnectorPair, stdoutConnectorPair, stderrConnectorPair)
387401
resp, err := ts.taskManager.ExecProcess(requestCtx, req, ts.runcService, ioConnectorSet)
388402
if err != nil {
389403
logger.WithError(err).Error("exec failed")

go.mod

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,11 @@ require (
66
github.com/StackExchange/wmi v0.0.0-20181212234831-e0a55b97c705 // indirect
77
github.com/containerd/cgroups v0.0.0-20181105182409-82cb49fc1779 // indirect
88
github.com/containerd/console v0.0.0-20181022165439-0650fd9eeb50 // indirect
9-
github.com/containerd/containerd v1.2.1-0.20190604174651-04e7747e2952
9+
github.com/containerd/containerd v1.2.1-0.20190626153021-bb9616ba206c
1010
github.com/containerd/continuity v0.0.0-20181027224239-bea7585dbfac
1111
github.com/containerd/fifo v0.0.0-20180307165137-3d5202aec260
1212
github.com/containerd/go-runc v0.0.0-20190226155025-7d11b49dc076 // indirect
13-
github.com/containerd/ttrpc v0.0.0-20190529185706-a5bd8ce9e40b
13+
github.com/containerd/ttrpc v0.0.0-20190613183316-1fb3814edf44
1414
github.com/containerd/typeurl v0.0.0-20181015155603-461401dc8f19
1515
github.com/coreos/go-systemd v0.0.0-20181031085051-9002847aa142 // indirect
1616
github.com/docker/distribution v2.7.1+incompatible // indirect

go.sum

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,16 +20,16 @@ github.com/containerd/cgroups v0.0.0-20181105182409-82cb49fc1779 h1:j1IsLW6/hNZP
2020
github.com/containerd/cgroups v0.0.0-20181105182409-82cb49fc1779/go.mod h1:X9rLEHIqSf/wfK8NsPqxJmeZgW4pcfzdXITDrUSJ6uI=
2121
github.com/containerd/console v0.0.0-20181022165439-0650fd9eeb50 h1:WMpHmC6AxwWb9hMqhudkqG7A/p14KiMnl6d3r1iUMjU=
2222
github.com/containerd/console v0.0.0-20181022165439-0650fd9eeb50/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw=
23-
github.com/containerd/containerd v1.2.1-0.20190604174651-04e7747e2952 h1:Qhl6R3Guhan+5vb5rrcJ/FkoW1wULTw6QOQ0zqDSxjw=
24-
github.com/containerd/containerd v1.2.1-0.20190604174651-04e7747e2952/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
23+
github.com/containerd/containerd v1.2.1-0.20190626153021-bb9616ba206c h1:m/ToFT22QUZDGCSrSwiayu75/NDnTWIeHGNY770sLiU=
24+
github.com/containerd/containerd v1.2.1-0.20190626153021-bb9616ba206c/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
2525
github.com/containerd/continuity v0.0.0-20181027224239-bea7585dbfac h1:PThQaO4yCvJzJBUW1XoFQxLotWRhvX2fgljJX8yrhFI=
2626
github.com/containerd/continuity v0.0.0-20181027224239-bea7585dbfac/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
2727
github.com/containerd/fifo v0.0.0-20180307165137-3d5202aec260 h1:XGyg7oTtD0DoRFhbpV6x1WfV0flKC4UxXU7ab1zC08U=
2828
github.com/containerd/fifo v0.0.0-20180307165137-3d5202aec260/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI=
2929
github.com/containerd/go-runc v0.0.0-20190226155025-7d11b49dc076 h1:biYGul6kwz5/Lh6UxkYQyRKPeYA/ZL5n2pdCAcYUpLA=
3030
github.com/containerd/go-runc v0.0.0-20190226155025-7d11b49dc076/go.mod h1:IV7qH3hrUgRmyYrtgEeGWJfWbgcHL9CSRruz2Vqcph0=
31-
github.com/containerd/ttrpc v0.0.0-20190529185706-a5bd8ce9e40b h1:srN6TO3+pkxySiWdCvVUz3uR8HXhpqhOmAs57BfhYFo=
32-
github.com/containerd/ttrpc v0.0.0-20190529185706-a5bd8ce9e40b/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o=
31+
github.com/containerd/ttrpc v0.0.0-20190613183316-1fb3814edf44 h1:vG5QXCUakUhR2CRI44aD3joCWcvb5mfZRxcwVqBVGeU=
32+
github.com/containerd/ttrpc v0.0.0-20190613183316-1fb3814edf44/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o=
3333
github.com/containerd/typeurl v0.0.0-20181015155603-461401dc8f19 h1:gzdItdct+4eLnZxiZi1YcIXx3uo5QWa/xXKnsldEqY8=
3434
github.com/containerd/typeurl v0.0.0-20181015155603-461401dc8f19/go.mod h1:Cm3kwCdlkCfMSHURc+r6fwoGH6/F1hH3S4sg0rLFWPc=
3535
github.com/coreos/go-systemd v0.0.0-20181031085051-9002847aa142 h1:3jFq2xL4ZajGK4aZY8jz+DAF0FHjI51BXjjSwCzS1Dk=

internal/vm/agent.go

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
// Copyright 2018-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License"). You may
4+
// not use this file except in compliance with the License. A copy of the
5+
// License is located at
6+
//
7+
// http://aws.amazon.com/apache2.0/
8+
//
9+
// or in the "license" file accompanying this file. This file is distributed
10+
// on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
11+
// express or implied. See the License for the specific language governing
12+
// permissions and limitations under the License.
13+
14+
package vm
15+
16+
import (
17+
"net/url"
18+
19+
"github.com/sirupsen/logrus"
20+
)
21+
22+
// IsAgentOnlyIO checks whether Stdout target is agent only in order to allow
23+
// log redirection entirely within the VM (currently cio.BinaryIO and cio.LogFile)
24+
func IsAgentOnlyIO(stdout string, logger *logrus.Entry) bool {
25+
parsed, err := url.Parse(stdout)
26+
if err != nil {
27+
logger.WithError(err).Debugf("invalid URL %q", stdout)
28+
return false
29+
}
30+
31+
switch parsed.Scheme {
32+
case "binary", "file":
33+
return true
34+
default:
35+
return false
36+
}
37+
}
38+
39+
// nullIOProxy represents an empty IOProxy implementation for cases when there is no need to
40+
// stream logs from the Agent through vsock.
41+
type nullIOProxy struct{}
42+
43+
// NewNullIOProxy creates an empty IOProxy
44+
func NewNullIOProxy() IOProxy {
45+
return &nullIOProxy{}
46+
}
47+
48+
func (*nullIOProxy) start(proc *vmProc) (ioInitDone <-chan error, ioCopyDone <-chan error) {
49+
initCh := make(chan error)
50+
close(initCh)
51+
52+
copyCh := make(chan error)
53+
close(copyCh)
54+
55+
return initCh, copyCh
56+
}

internal/vm/agent_test.go

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// Copyright 2018-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License"). You may
4+
// not use this file except in compliance with the License. A copy of the
5+
// License is located at
6+
//
7+
// http://aws.amazon.com/apache2.0/
8+
//
9+
// or in the "license" file accompanying this file. This file is distributed
10+
// on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
11+
// express or implied. See the License for the specific language governing
12+
// permissions and limitations under the License.
13+
14+
package vm
15+
16+
import (
17+
"testing"
18+
19+
"github.com/containerd/containerd/cio"
20+
"github.com/containerd/containerd/log"
21+
"github.com/stretchr/testify/assert"
22+
)
23+
24+
func TestAgentOnlyIO(t *testing.T) {
25+
assert.True(t, IsAgentOnlyIO(creator(t, cio.BinaryIO("/root/binary", nil)), log.L))
26+
assert.True(t, IsAgentOnlyIO(creator(t, cio.LogFile("/log.txt")), log.L))
27+
}
28+
29+
func TestNonAgentIO(t *testing.T) {
30+
assert.False(t, IsAgentOnlyIO("fifo://test", log.L))
31+
assert.False(t, IsAgentOnlyIO("/tmp/path", log.L))
32+
assert.False(t, IsAgentOnlyIO("", log.L))
33+
}
34+
35+
func creator(t *testing.T, creator cio.Creator) string {
36+
t.Helper()
37+
38+
io, err := creator("!")
39+
assert.NoError(t, err)
40+
41+
return io.Config().Stdout
42+
}

0 commit comments

Comments
 (0)