github.com/GoogleContainerTools/skaffold@v1.39.18/pkg/skaffold/log/stream/stream.go (about)

     1  /*
     2  Copyright 2021 The Skaffold Authors
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package stream
    18  
    19  import (
    20  	"bufio"
    21  	"context"
    22  	"fmt"
    23  	"io"
    24  	"strings"
    25  
    26  	"github.com/GoogleContainerTools/skaffold/pkg/skaffold/log"
    27  	olog "github.com/GoogleContainerTools/skaffold/pkg/skaffold/output/log"
    28  )
    29  
    30  //nolint:golint
    31  func StreamRequest(ctx context.Context, out io.Writer, formatter log.Formatter, rc io.Reader) error {
    32  	r := bufio.NewReader(rc)
    33  	for {
    34  		select {
    35  		case <-ctx.Done():
    36  			olog.Entry(ctx).Infof("%s interrupted", formatter.Name())
    37  			return nil
    38  		default:
    39  			// Read up to newline
    40  			line, err := r.ReadString('\n')
    41  			// As per https://github.com/kubernetes/kubernetes/blob/017b359770e333eacd3efcb4174f1d464c208400/test/e2e/storage/podlogs/podlogs.go#L214
    42  			// Filter out the expected "end of stream" error message and
    43  			// attempts to read logs from a container that was deleted due to re-deploy or
    44  			// attempts to read logs from a container that is not ready yet.
    45  			if err == io.EOF {
    46  				if !isEmptyOrContainerNotReady(line) {
    47  					formatter.PrintLine(out, line)
    48  				}
    49  				return nil
    50  			}
    51  			if err != nil {
    52  				return fmt.Errorf("reading bytes from log stream: %w", err)
    53  			}
    54  			formatter.PrintLine(out, line)
    55  		}
    56  	}
    57  }
    58  
    59  func isEmptyOrContainerNotReady(line string) bool {
    60  	return line == "" ||
    61  		strings.HasPrefix(line, "rpc error: code = Unknown desc = Error: No such container:") ||
    62  		strings.HasPrefix(line, "unable to retrieve container logs for ") ||
    63  		strings.HasPrefix(line, "Unable to retrieve container logs for ")
    64  }