Handle stderr in stream processors
Signed-off-by: Michael Crosby <crosbymichael@gmail.com>
This commit is contained in:
parent
3fded74bc7
commit
552a0b1be5
@ -76,11 +76,14 @@ func (s *fsApplier) Apply(ctx context.Context, desc ocispec.Descriptor, mounts [
|
|||||||
}
|
}
|
||||||
defer ra.Close()
|
defer ra.Close()
|
||||||
|
|
||||||
|
var processors []diff.StreamProcessor
|
||||||
processor := diff.NewProcessorChain(desc.MediaType, content.NewReader(ra))
|
processor := diff.NewProcessorChain(desc.MediaType, content.NewReader(ra))
|
||||||
|
processors = append(processors, processor)
|
||||||
for {
|
for {
|
||||||
if processor, err = diff.GetProcessor(ctx, processor, config.ProcessorPayloads); err != nil {
|
if processor, err = diff.GetProcessor(ctx, processor, config.ProcessorPayloads); err != nil {
|
||||||
return emptyDesc, errors.Wrapf(err, "failed to get stream processor for %s", desc.MediaType)
|
return emptyDesc, errors.Wrapf(err, "failed to get stream processor for %s", desc.MediaType)
|
||||||
}
|
}
|
||||||
|
processors = append(processors, processor)
|
||||||
if processor.MediaType() == ocispec.MediaTypeImageLayer {
|
if processor.MediaType() == ocispec.MediaTypeImageLayer {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@ -102,6 +105,16 @@ func (s *fsApplier) Apply(ctx context.Context, desc ocispec.Descriptor, mounts [
|
|||||||
}); err != nil {
|
}); err != nil {
|
||||||
return emptyDesc, err
|
return emptyDesc, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for _, p := range processors {
|
||||||
|
if ep, ok := p.(interface {
|
||||||
|
Err() error
|
||||||
|
}); ok {
|
||||||
|
if err := ep.Err(); err != nil {
|
||||||
|
return emptyDesc, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return ocispec.Descriptor{
|
return ocispec.Descriptor{
|
||||||
MediaType: ocispec.MediaTypeImageLayer,
|
MediaType: ocispec.MediaTypeImageLayer,
|
||||||
Size: rc.c,
|
Size: rc.c,
|
||||||
|
@ -25,14 +25,17 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
"sync"
|
||||||
|
|
||||||
"github.com/gogo/protobuf/proto"
|
"github.com/gogo/protobuf/proto"
|
||||||
"github.com/gogo/protobuf/types"
|
"github.com/gogo/protobuf/types"
|
||||||
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewBinaryProcessor returns a binary processor for use with processing content streams
|
// NewBinaryProcessor returns a binary processor for use with processing content streams
|
||||||
func NewBinaryProcessor(ctx context.Context, imt, rmt string, stream StreamProcessor, name string, args []string, payload *types.Any) (StreamProcessor, error) {
|
func NewBinaryProcessor(ctx context.Context, imt, rmt string, stream StreamProcessor, name string, args []string, payload *types.Any) (StreamProcessor, error) {
|
||||||
cmd := exec.CommandContext(ctx, name, args...)
|
cmd := exec.CommandContext(ctx, name, args...)
|
||||||
|
cmd.Env = os.Environ()
|
||||||
|
|
||||||
var payloadC io.Closer
|
var payloadC io.Closer
|
||||||
if payload != nil {
|
if payload != nil {
|
||||||
@ -71,10 +74,19 @@ func NewBinaryProcessor(ctx context.Context, imt, rmt string, stream StreamProce
|
|||||||
}
|
}
|
||||||
cmd.Stdout = w
|
cmd.Stdout = w
|
||||||
|
|
||||||
|
stderr := bytes.NewBuffer(nil)
|
||||||
|
cmd.Stderr = stderr
|
||||||
|
|
||||||
if err := cmd.Start(); err != nil {
|
if err := cmd.Start(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
go cmd.Wait()
|
p := &binaryProcessor{
|
||||||
|
cmd: cmd,
|
||||||
|
r: r,
|
||||||
|
mt: rmt,
|
||||||
|
stderr: stderr,
|
||||||
|
}
|
||||||
|
go p.wait()
|
||||||
|
|
||||||
// close after start and dup
|
// close after start and dup
|
||||||
w.Close()
|
w.Close()
|
||||||
@ -84,17 +96,33 @@ func NewBinaryProcessor(ctx context.Context, imt, rmt string, stream StreamProce
|
|||||||
if payloadC != nil {
|
if payloadC != nil {
|
||||||
payloadC.Close()
|
payloadC.Close()
|
||||||
}
|
}
|
||||||
return &binaryProcessor{
|
return p, nil
|
||||||
cmd: cmd,
|
|
||||||
r: r,
|
|
||||||
mt: rmt,
|
|
||||||
}, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type binaryProcessor struct {
|
type binaryProcessor struct {
|
||||||
cmd *exec.Cmd
|
cmd *exec.Cmd
|
||||||
r *os.File
|
r *os.File
|
||||||
mt string
|
mt string
|
||||||
|
stderr *bytes.Buffer
|
||||||
|
|
||||||
|
mu sync.Mutex
|
||||||
|
err error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *binaryProcessor) Err() error {
|
||||||
|
c.mu.Lock()
|
||||||
|
defer c.mu.Unlock()
|
||||||
|
return c.err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *binaryProcessor) wait() {
|
||||||
|
if err := c.cmd.Wait(); err != nil {
|
||||||
|
if _, ok := err.(*exec.ExitError); ok {
|
||||||
|
c.mu.Lock()
|
||||||
|
c.err = errors.New(c.stderr.String())
|
||||||
|
c.mu.Unlock()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *binaryProcessor) File() *os.File {
|
func (c *binaryProcessor) File() *os.File {
|
||||||
|
@ -27,10 +27,12 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"sync"
|
||||||
|
|
||||||
winio "github.com/Microsoft/go-winio"
|
winio "github.com/Microsoft/go-winio"
|
||||||
"github.com/gogo/protobuf/proto"
|
"github.com/gogo/protobuf/proto"
|
||||||
"github.com/gogo/protobuf/types"
|
"github.com/gogo/protobuf/types"
|
||||||
|
"github.com/pkg/errors"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -39,6 +41,7 @@ const processorPipe = "STREAM_PROCESSOR_PIPE"
|
|||||||
// NewBinaryProcessor returns a binary processor for use with processing content streams
|
// NewBinaryProcessor returns a binary processor for use with processing content streams
|
||||||
func NewBinaryProcessor(ctx context.Context, imt, rmt string, stream StreamProcessor, name string, args []string, payload *types.Any) (StreamProcessor, error) {
|
func NewBinaryProcessor(ctx context.Context, imt, rmt string, stream StreamProcessor, name string, args []string, payload *types.Any) (StreamProcessor, error) {
|
||||||
cmd := exec.CommandContext(ctx, name, args...)
|
cmd := exec.CommandContext(ctx, name, args...)
|
||||||
|
cmd.Env = os.Environ()
|
||||||
|
|
||||||
if payload != nil {
|
if payload != nil {
|
||||||
data, err := proto.Marshal(payload)
|
data, err := proto.Marshal(payload)
|
||||||
@ -84,28 +87,52 @@ func NewBinaryProcessor(ctx context.Context, imt, rmt string, stream StreamProce
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
cmd.Stdout = w
|
cmd.Stdout = w
|
||||||
|
stderr := bytes.NewBuffer(nil)
|
||||||
|
cmd.Stderr = stderr
|
||||||
|
|
||||||
if err := cmd.Start(); err != nil {
|
if err := cmd.Start(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
go cmd.Wait()
|
p := &binaryProcessor{
|
||||||
|
cmd: cmd,
|
||||||
|
r: r,
|
||||||
|
mt: rmt,
|
||||||
|
stderr: stderr,
|
||||||
|
}
|
||||||
|
go p.wait()
|
||||||
|
|
||||||
// close after start and dup
|
// close after start and dup
|
||||||
w.Close()
|
w.Close()
|
||||||
if closer != nil {
|
if closer != nil {
|
||||||
closer()
|
closer()
|
||||||
}
|
}
|
||||||
return &binaryProcessor{
|
return p, nil
|
||||||
cmd: cmd,
|
|
||||||
r: r,
|
|
||||||
mt: rmt,
|
|
||||||
}, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type binaryProcessor struct {
|
type binaryProcessor struct {
|
||||||
cmd *exec.Cmd
|
cmd *exec.Cmd
|
||||||
r *os.File
|
r *os.File
|
||||||
mt string
|
mt string
|
||||||
|
stderr *bytes.Buffer
|
||||||
|
|
||||||
|
mu sync.Mutex
|
||||||
|
err error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *binaryProcessor) Err() error {
|
||||||
|
c.mu.Lock()
|
||||||
|
defer c.mu.Unlock()
|
||||||
|
return c.err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *binaryProcessor) wait() {
|
||||||
|
if err := c.cmd.Wait(); err != nil {
|
||||||
|
if _, ok := err.(*exec.ExitError); ok {
|
||||||
|
c.mu.Lock()
|
||||||
|
c.err = errors.New(c.stderr.String())
|
||||||
|
c.mu.Unlock()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *binaryProcessor) File() *os.File {
|
func (c *binaryProcessor) File() *os.File {
|
||||||
|
Loading…
Reference in New Issue
Block a user