@@ -43,11 +43,9 @@ type cappedWriter struct {
4343 remain int
4444}
4545
46- var errNoRemain = errors .New ("no more space to write" )
47-
4846func (cw * cappedWriter ) Write (p []byte ) (int , error ) {
4947 if cw .remain <= 0 {
50- return 0 , errNoRemain
48+ return len ( p ), nil
5149 }
5250
5351 end := cw .remain
@@ -60,26 +58,35 @@ func (cw *cappedWriter) Write(p []byte) (int, error) {
6058 if err != nil {
6159 return written , err
6260 }
63- if written < len (p ) {
64- return written , errNoRemain
65- }
66- return written , nil
61+ return len (p ), nil
6762}
6863
6964func (cw * cappedWriter ) Close () error {
7065 return cw .w .Close ()
7166}
7267
68+ func (cw * cappedWriter ) isFull () bool {
69+ return cw .remain <= 0
70+ }
71+
7372// ExecSync executes a command in the container, and returns the stdout output.
7473// If command exits with a non-zero exit code, an error is returned.
7574func (c * criService ) ExecSync (ctx context.Context , r * runtime.ExecSyncRequest ) (* runtime.ExecSyncResponse , error ) {
7675 const maxStreamSize = 1024 * 1024 * 16
7776
7877 var stdout , stderr bytes.Buffer
78+
79+ // cappedWriter truncates the output. In that case, the size of
80+ // the ExecSyncResponse will hit the CRI plugin's gRPC response limit.
81+ // Thus the callers outside of the containerd process (e.g. Kubelet) never see
82+ // the truncated output.
83+ cout := & cappedWriter {w : cioutil .NewNopWriteCloser (& stdout ), remain : maxStreamSize }
84+ cerr := & cappedWriter {w : cioutil .NewNopWriteCloser (& stderr ), remain : maxStreamSize }
85+
7986 exitCode , err := c .execInContainer (ctx , r .GetContainerId (), execOptions {
8087 cmd : r .GetCmd (),
81- stdout : & cappedWriter { w : cioutil . NewNopWriteCloser ( & stdout ), remain : maxStreamSize } ,
82- stderr : & cappedWriter { w : cioutil . NewNopWriteCloser ( & stderr ), remain : maxStreamSize } ,
88+ stdout : cout ,
89+ stderr : cerr ,
8390 timeout : time .Duration (r .GetTimeout ()) * time .Second ,
8491 })
8592 if err != nil {
0 commit comments