github.com/GoogleContainerTools/skaffold@v1.39.18/pkg/skaffold/output/output.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 output
    18  
    19  import (
    20  	"context"
    21  	"io"
    22  	"os"
    23  	"time"
    24  
    25  	"github.com/GoogleContainerTools/skaffold/pkg/skaffold/constants"
    26  	eventV2 "github.com/GoogleContainerTools/skaffold/pkg/skaffold/event/v2"
    27  	"github.com/GoogleContainerTools/skaffold/pkg/skaffold/output/log"
    28  )
    29  
    30  const timestampFormat = "2006-01-02 15:04:05"
    31  
    32  type skaffoldWriter struct {
    33  	MainWriter  io.Writer
    34  	EventWriter io.Writer
    35  	task        constants.Phase
    36  	subtask     string
    37  
    38  	timestamps bool
    39  }
    40  
    41  func (s skaffoldWriter) Write(p []byte) (int, error) {
    42  	written := 0
    43  	if s.timestamps {
    44  		t, err := s.MainWriter.Write([]byte(time.Now().Format(timestampFormat) + " "))
    45  		if err != nil {
    46  			return t, err
    47  		}
    48  
    49  		written += t
    50  	}
    51  
    52  	n, err := s.MainWriter.Write(p)
    53  	if err != nil {
    54  		return n, err
    55  	}
    56  	if n != len(p) {
    57  		return n, io.ErrShortWrite
    58  	}
    59  
    60  	written += n
    61  
    62  	s.EventWriter.Write(p)
    63  
    64  	return written, nil
    65  }
    66  
    67  func GetWriter(ctx context.Context, out io.Writer, defaultColor int, forceColors bool, timestamps bool) io.Writer {
    68  	if _, isSW := out.(skaffoldWriter); isSW {
    69  		return out
    70  	}
    71  
    72  	return skaffoldWriter{
    73  		MainWriter:  SetupColors(ctx, out, defaultColor, forceColors),
    74  		EventWriter: eventV2.NewLogger(constants.DevLoop, "-1"),
    75  		timestamps:  timestamps,
    76  	}
    77  }
    78  
    79  func IsStdout(out io.Writer) bool {
    80  	sw, isSW := out.(skaffoldWriter)
    81  	if isSW {
    82  		out = sw.MainWriter
    83  	}
    84  	cw, isCW := out.(colorableWriter)
    85  	if isCW {
    86  		out = cw.Writer
    87  	}
    88  	return out == os.Stdout
    89  }
    90  
    91  // GetUnderlyingWriter returns the underlying writer if out is a colorableWriter
    92  func GetUnderlyingWriter(out io.Writer) io.Writer {
    93  	sw, isSW := out.(skaffoldWriter)
    94  	if isSW {
    95  		out = sw.MainWriter
    96  	}
    97  	cw, isCW := out.(colorableWriter)
    98  	if isCW {
    99  		out = cw.Writer
   100  	}
   101  	return out
   102  }
   103  
   104  // WithEventContext will return a new skaffoldWriter with the given parameters to be used for the event writer.
   105  // If the passed io.Writer is not a skaffoldWriter, then it is simply returned.
   106  func WithEventContext(ctx context.Context, out io.Writer, phase constants.Phase, subtaskID string) (io.Writer, context.Context) {
   107  	ctx = context.WithValue(ctx, log.ContextKey, log.EventContext{
   108  		Task:    phase,
   109  		Subtask: subtaskID,
   110  	})
   111  
   112  	if sw, isSW := out.(skaffoldWriter); isSW {
   113  		return skaffoldWriter{
   114  			MainWriter:  sw.MainWriter,
   115  			EventWriter: eventV2.NewLogger(phase, subtaskID),
   116  			task:        phase,
   117  			subtask:     subtaskID,
   118  			timestamps:  sw.timestamps,
   119  		}, ctx
   120  	}
   121  
   122  	return out, ctx
   123  }