func (i infoLogger) Info(message string) {
	if !i.enabled {
		return
	}
	if i.level > 0 {
		i.logger.debug(message)
	} else {
		i.logger.print(message)
	}
}
Info is part of the log.InfoLogger interface
package cli
import (
	"bytes"
	"fmt"
	"io"
	"runtime"
	"strings"
	"sync"
	"sync/atomic"
	"sigs.k8s.io/kind/pkg/log"
	"sigs.k8s.io/kind/pkg/internal/env"
)
type Logger struct {
	writer     io.Writer
	writerMu   sync.Mutex
	verbosity  log.Level
	bufferPool *bufferPool
	isSmartWriter bool
}
var _ log.Logger = &Logger{}
func NewLogger(writer io.Writer, verbosity log.Level) *Logger {
	l := &Logger{
		verbosity:  verbosity,
		bufferPool: newBufferPool(),
	}
	l.SetWriter(writer)
	return l
}
func (l *Logger) SetWriter(w io.Writer) {
	l.writerMu.Lock()
	defer l.writerMu.Unlock()
	l.writer = w
	_, isSpinner := w.(*Spinner)
	l.isSmartWriter = isSpinner || env.IsSmartTerminal(w)
}
func (l *Logger) ColorEnabled() bool {
	l.writerMu.Lock()
	defer l.writerMu.Unlock()
	return l.isSmartWriter
}
func (l *Logger) getVerbosity() log.Level {
	return log.Level(atomic.LoadInt32((*int32)(&l.verbosity)))
}
func (l *Logger) SetVerbosity(verbosity log.Level) {
	atomic.StoreInt32((*int32)(&l.verbosity), int32(verbosity))
}
func (l *Logger) write(p []byte) (n int, err error) {
	l.writerMu.Lock()
	defer l.writerMu.Unlock()
	return l.writer.Write(p)
}
func (l *Logger) writeBuffer(buf *bytes.Buffer) {
	if buf.Len() == 0 || buf.Bytes()[buf.Len()-1] != '\n' {
		buf.WriteByte('\n')
	}
	_, _ = l.write(buf.Bytes())
}
func (l *Logger) print(message string) {
	buf := bytes.NewBufferString(message)
	l.writeBuffer(buf)
}
func (l *Logger) printf(format string, args ...interface{}) {
	buf := l.bufferPool.Get()
	fmt.Fprintf(buf, format, args...)
	l.writeBuffer(buf)
	l.bufferPool.Put(buf)
}
func addDebugHeader(buf *bytes.Buffer) {
	_, file, line, ok := runtime.Caller(3)
	if !ok {
		file = "???"
		line = 1
	} else {
		if slash := strings.LastIndex(file, "/"); slash >= 0 {
			path := file
			file = path[slash+1:]
			if dirsep := strings.LastIndex(path[:slash], "/"); dirsep >= 0 {
				file = path[dirsep+1:]
			}
		}
	}
	buf.Grow(len(file) + 11)  
	buf.WriteString("DEBUG: ")
	buf.WriteString(file)
	buf.WriteByte(':')
	fmt.Fprintf(buf, "%d", line)
	buf.WriteByte(']')
	buf.WriteByte(' ')
}
func (l *Logger) debug(message string) {
	buf := l.bufferPool.Get()
	addDebugHeader(buf)
	buf.WriteString(message)
	l.writeBuffer(buf)
	l.bufferPool.Put(buf)
}
func (l *Logger) debugf(format string, args ...interface{}) {
	buf := l.bufferPool.Get()
	addDebugHeader(buf)
	fmt.Fprintf(buf, format, args...)
	l.writeBuffer(buf)
	l.bufferPool.Put(buf)
}
func (l *Logger) Warn(message string) {
	l.print(message)
}
func (l *Logger) Warnf(format string, args ...interface{}) {
	l.printf(format, args...)
}
func (l *Logger) Error(message string) {
	l.print(message)
}
func (l *Logger) Errorf(format string, args ...interface{}) {
	l.printf(format, args...)
}
func (l *Logger) V(level log.Level) log.InfoLogger {
	return infoLogger{
		logger:  l,
		level:   level,
		enabled: level <= l.getVerbosity(),
	}
}
type infoLogger struct {
	logger  *Logger
	level   log.Level
	enabled bool
}
func (i infoLogger) Enabled() bool {
	return i.enabled
}