From b42b80b897b37a89aa6230e20c79c07714b9bdf4 Mon Sep 17 00:00:00 2001 From: Reed Allman Date: Sat, 13 Apr 2019 11:10:51 -0700 Subject: [PATCH 1/9] move log config up to getcall we have WithLogger already, we just need to use it. this moves the config of the logger itself up to be a call option which makes it less brittle in GetCall to hit the path where it might get accidentally turned on. removes the old buffer and io.Reader on stderr so that we could upload logs, we only need the logrus logger for now and it was a bit of a tangled mess. TODO need to add config bit to set the default level to 'info' so that we get logs out of these guys in the agent config (pure runner is left alone to off), with ability to change to debug or turn off altogether. NOTE: this fixes #1328 by putting a write guard after close and not using the line writer for different writers --- api/agent/agent.go | 9 +- api/agent/call.go | 25 +++--- api/agent/func_logger.go | 153 +++++++++------------------------- api/server/runner_fninvoke.go | 25 +++--- 4 files changed, 72 insertions(+), 140 deletions(-) diff --git a/api/agent/agent.go b/api/agent/agent.go index 74f4d3c95a..baa1f31135 100644 --- a/api/agent/agent.go +++ b/api/agent/agent.go @@ -645,8 +645,8 @@ func (s *hotSlot) dispatch(ctx context.Context, call *call) error { defer span.End() // TODO it's possible we can get rid of this (after getting rid of logs API) - may need for call id/debug mode still - // TODO there's a timeout race for swapping this back if the container doesn't get killed for timing out, and don't you forget it swapBack := s.container.swap(call.stderr, &call.Stats) + defer call.stderr.Close() defer swapBack() req := createUDSRequest(ctx, call) @@ -1204,9 +1204,11 @@ func newHotContainer(ctx context.Context, evictor Evictor, call *call, cfg *Conf if _, ok := stderr.(common.NoopReadWriteCloser); !ok { gw := common.NewGhostWriter() buf1 := bufPool.Get().(*bytes.Buffer) - sec := &nopCloser{&logWriter{ + // TODO(reed): this logger may have garbage in it between calls, easy fix + // is to make a new one each swap, it's cheap enough to be doable. + sec := &nopCloser{newLogWriter( logrus.WithFields(logrus.Fields{"tag": "stderr", "app_id": call.AppID, "fn_id": call.FnID, "image": call.Image, "container_id": id}), - }} + )} gw.Swap(newLineWriterWithBuffer(buf1, sec)) stderr = gw bufs = append(bufs, buf1) @@ -1336,6 +1338,7 @@ func (c *container) DisableNet() bool { return c.disableNet } func (c *container) WriteStat(ctx context.Context, stat driver_stats.Stat) { for key, value := range stat.Metrics { if m, ok := dockerMeasures[key]; ok { + common.Logger(ctx).WithField(key, value).Info("container stats") stats.Record(ctx, m.M(int64(value))) } } diff --git a/api/agent/call.go b/api/agent/call.go index 19c7929ac5..4ec2e20b41 100644 --- a/api/agent/call.go +++ b/api/agent/call.go @@ -5,6 +5,7 @@ import ( "errors" "fmt" "io" + "io/ioutil" "net/http" "path/filepath" "strings" @@ -212,6 +213,14 @@ func WithDockerAuth(auth docker.Auther) CallOpt { } } +func (a *agent) WithStderrLogger() CallOpt { + return func(c *call) error { + // XXX(reed): allow configuring the level / turning off + c.stderr = setupLogger(c.Call) + return nil + } +} + // GetCall builds a Call that can be used to submit jobs to the agent. func (a *agent) GetCall(opts ...CallOpt) (Call, error) { var c call @@ -253,20 +262,17 @@ func (a *agent) GetCall(opts ...CallOpt) (Call, error) { } c.Call.Config["FN_LISTENER"] = "unix:" + filepath.Join(iofsDockerMountDest, udsFilename) c.Call.Config["FN_FORMAT"] = "http-stream" // TODO: remove this after fdk's forget what it means - // TODO we could set type here too, for now, or anything else not based in fn/app/trigger config setupCtx(&c) c.ct = a if c.stderr == nil { - // TODO(reed): is line writer is vulnerable to attack? - // XXX(reed): forcing this as default is not great / configuring it isn't great either. reconsider. - c.stderr = setupLogger(c.req.Context(), a.cfg.MaxLogSize, !a.cfg.DisableDebugUserLogs, c.Call) + // this disables logs in driver (at container level) + c.stderr = common.NoopReadWriteCloser{} } if c.respWriter == nil { - // send function output to logs if no writer given (TODO no longer need w/o async?) - // TODO we could/should probably make this explicit to GetCall, ala 'WithLogger', but it's dupe code (who cares?) - c.respWriter = c.stderr + // TODO: we could make this an error, up to us + c.respWriter = ioutil.Discard } return &c, nil @@ -283,7 +289,7 @@ type call struct { respWriter io.Writer req *http.Request - stderr io.ReadWriteCloser + stderr io.WriteCloser ct callTrigger slots *slotQueue requestState RequestState @@ -373,9 +379,6 @@ func (c *call) End(ctx context.Context, errIn error) error { // ensure stats histogram is reasonably bounded c.Call.Stats = stats.Decimate(240, c.Call.Stats) - // NOTE call this after InsertLog or the buffer will get reset - c.stderr.Close() - if err := c.ct.fireAfterCall(ctx, c.Model()); err != nil { return err } diff --git a/api/agent/func_logger.go b/api/agent/func_logger.go index d99f787960..18f72a150e 100644 --- a/api/agent/func_logger.go +++ b/api/agent/func_logger.go @@ -2,84 +2,48 @@ package agent import ( "bytes" - "context" - "fmt" "io" "sync" + "sync/atomic" - "github.com/fnproject/fn/api/common" "github.com/fnproject/fn/api/models" "github.com/sirupsen/logrus" ) var ( bufPool = &sync.Pool{New: func() interface{} { return new(bytes.Buffer) }} - logPool = &sync.Pool{New: func() interface{} { return new(bytes.Buffer) }} ) -// setupLogger returns a ReadWriteCloser that may have: -// * [always] writes bytes to a size limited buffer, that can be read from using io.Reader // * [always] writes bytes per line to stderr as DEBUG -// -// To prevent write failures from failing the call or any other writes, -// multiWriteCloser ignores errors. Close will flush the line writers -// appropriately. The returned io.ReadWriteCloser is not safe for use after -// calling Close. -func setupLogger(ctx context.Context, maxSize uint64, debug bool, c *models.Call) io.ReadWriteCloser { +func setupLogger(c *models.Call) io.WriteCloser { lbuf := bufPool.Get().(*bytes.Buffer) - dbuf := logPool.Get().(*bytes.Buffer) - close := func() error { + close := func() { // TODO we may want to toss out buffers that grow to grotesque size but meh they will prob get GC'd lbuf.Reset() - dbuf.Reset() bufPool.Put(lbuf) - logPool.Put(dbuf) - return nil } - // we don't need to log per line to db, but we do need to limit it - limitw := &nopCloser{newLimitWriter(int(maxSize), dbuf)} - - // order matters, in that closer should be last and limit should be next to last - mw := make(multiWriteCloser, 0, 3) - - if debug { - // accumulate all line writers, wrap in same line writer (to re-use buffer) - stderrLogger := common.Logger(ctx).WithFields(logrus.Fields{"user_log": true, "app_id": c.AppID, "fn_id": c.FnID, "image": c.Image, "call_id": c.ID}) - loggo := &nopCloser{&logWriter{stderrLogger}} - - // we don't need to limit the log writer(s), but we do need it to dispense lines - linew := newLineWriterWithBuffer(lbuf, loggo) - mw = append(mw, linew) + stderrLogger := logrus.WithFields(logrus.Fields{"user_log": true, "app_id": c.AppID, "fn_id": c.FnID, "image": c.Image, "call_id": c.ID}) + loggo := newLogWriter(stderrLogger) + linew := newLineWriterWithBuffer(lbuf, loggo) + linew = &fCloser{ + close: func() error { + err := linew.Close() + close() + return err + }, } - - mw = append(mw, limitw, &fCloser{close}) - return &rwc{mw, dbuf} + return linew } -// implements io.ReadWriteCloser, fmt.Stringer and Bytes() -// TODO WriteString and ReadFrom would be handy to implement, -// ReadFrom is a little involved. -type rwc struct { - io.WriteCloser - - // buffer is not embedded since it would bypass calls to WriteCloser.Write - // in cases such as WriteString and ReadFrom - b *bytes.Buffer -} - -func (r *rwc) Read(b []byte) (int, error) { return r.b.Read(b) } -func (r *rwc) String() string { return r.b.String() } -func (r *rwc) Bytes() []byte { return r.b.Bytes() } - -// implements passthrough Write & closure call in Close +// implements passthrough WriteCloser with overwritable Close type fCloser struct { + io.Writer close func() error } -func (f *fCloser) Write(b []byte) (int, error) { return len(b), nil } -func (f *fCloser) Close() error { return f.close() } +func (f *fCloser) Close() error { return f.close() } type nopCloser struct { io.Writer @@ -87,44 +51,41 @@ type nopCloser struct { func (n *nopCloser) Close() error { return nil } -// multiWriteCloser ignores all errors from inner writers. you say, oh, this is a bad idea? -// yes, well, we were going to silence them all individually anyway, so let's not be shy about it. -// the main thing we need to ensure is that every close is called, even if another errors. -// XXX(reed): maybe we should log it (for syslog, it may help debug, maybe we just log that one) -type multiWriteCloser []io.WriteCloser - -func (m multiWriteCloser) Write(b []byte) (n int, err error) { - for _, mw := range m { - mw.Write(b) - } - return len(b), nil -} - -func (m multiWriteCloser) Close() (err error) { - for _, mw := range m { - mw.Close() - } - return nil -} - // logWriter will log (to real stderr) every call to Write as a line. it should // be wrapped with a lineWriter so that the output makes sense. type logWriter struct { + // level string // XXX(reed): logrus.FieldLogger + closed uint32 +} + +func newLogWriter(logger logrus.FieldLogger) io.WriteCloser { + return &logWriter{FieldLogger: logger} } func (l *logWriter) Write(b []byte) (int, error) { + if atomic.LoadUint32(&l.closed) == 1 { + // we don't want to return 0/error or the container will get shut down + return len(b), nil + } l.Debug(string(b)) return len(b), nil } +func (l *logWriter) Close() error { + atomic.StoreUint32(&l.closed, 1) + return nil +} + // lineWriter buffers all calls to Write and will call Write // on the underlying writer once per new line. Close must // be called to ensure that the buffer is flushed, and a newline // will be appended in Close if none is present. +// TODO(reed): is line writer is vulnerable to attack? type lineWriter struct { - b *bytes.Buffer - w io.WriteCloser + b *bytes.Buffer + w io.WriteCloser + closed uint32 } func newLineWriter(w io.WriteCloser) io.WriteCloser { @@ -136,6 +97,10 @@ func newLineWriterWithBuffer(b *bytes.Buffer, w io.WriteCloser) io.WriteCloser { } func (li *lineWriter) Write(ogb []byte) (int, error) { + if atomic.LoadUint32(&li.closed) == 1 { + // we don't want to return 0/error or the container will shut down + return len(ogb), nil + } li.b.Write(ogb) // bytes.Buffer is guaranteed, read it! for { @@ -159,6 +124,8 @@ func (li *lineWriter) Write(ogb []byte) (int, error) { } func (li *lineWriter) Close() error { + atomic.StoreUint32(&li.closed, 1) + defer li.w.Close() // MUST close this (after writing last line) // flush the remaining bytes in the buffer to underlying writer, adding a @@ -174,41 +141,3 @@ func (li *lineWriter) Close() error { _, err := li.w.Write(b) return err } - -// io.Writer that allows limiting bytes written to w -// TODO change to use clamp writer, this is dupe code -type limitDiscardWriter struct { - n, max int - io.Writer -} - -func newLimitWriter(max int, w io.Writer) io.Writer { - return &limitDiscardWriter{max: max, Writer: w} -} - -func (l *limitDiscardWriter) Write(b []byte) (int, error) { - inpLen := len(b) - if l.n >= l.max { - return inpLen, nil - } - - if l.n+inpLen >= l.max { - // cut off to prevent gigantic line attack - b = b[:l.max-l.n] - } - - n, err := l.Writer.Write(b) - l.n += n - - if l.n >= l.max { - // write in truncation message to log once - l.Writer.Write([]byte(fmt.Sprintf("\n-----max log size %d bytes exceeded, truncating log-----\n", l.max))) - } else if n != len(b) { - // Is this truly a partial write? We'll be honest if that's the case. - return n, err - } - - // yes, we lie... this is to prevent callers to blow up, we always pretend - // that we were able to write the entire buffer. - return inpLen, err -} diff --git a/api/server/runner_fninvoke.go b/api/server/runner_fninvoke.go index 54e4c1adb0..cf249898fc 100644 --- a/api/server/runner_fninvoke.go +++ b/api/server/runner_fninvoke.go @@ -92,11 +92,15 @@ func (s *Server) fnInvoke(resp http.ResponseWriter, req *http.Request, app *mode // buffer the response before writing it out to client to prevent partials from trying to stream buf := bufPool.Get().(*bytes.Buffer) buf.Reset() - var writer ResponseBuffer + var opts []agent.CallOpt + opts = append(opts, agent.FromHTTPFnRequest(app, fn, req)) + + var writer ResponseBuffer isDetached := req.Header.Get("Fn-Invoke-Type") == models.TypeDetached if isDetached { writer = agent.NewDetachedResponseWriter(202) + opts = append(opts, agent.InvokeDetached()) } else { writer = &syncResponseWriter{ headers: resp.Header(), @@ -104,7 +108,12 @@ func (s *Server) fnInvoke(resp http.ResponseWriter, req *http.Request, app *mode Buffer: buf, } } - opts := getCallOptions(req, app, fn, trig, writer) + + opts = append(opts, agent.WithWriter(rw)) + opts = append(opts, agent.WithStderrLogger()) + if trig != nil { + opts = append(opts, agent.WithTrigger(trig)) + } call, err := s.agent.GetCall(opts...) if err != nil { @@ -137,16 +146,4 @@ func (s *Server) fnInvoke(resp http.ResponseWriter, req *http.Request, app *mode } func getCallOptions(req *http.Request, app *models.App, fn *models.Fn, trig *models.Trigger, rw http.ResponseWriter) []agent.CallOpt { - var opts []agent.CallOpt - opts = append(opts, agent.WithWriter(rw)) // XXX (reed): order matters [for now] - opts = append(opts, agent.FromHTTPFnRequest(app, fn, req)) - - if req.Header.Get("Fn-Invoke-Type") == models.TypeDetached { - opts = append(opts, agent.InvokeDetached()) - } - - if trig != nil { - opts = append(opts, agent.WithTrigger(trig)) - } - return opts } From d5708209a65f7a5a63a3360d8d6ad725aa245f5e Mon Sep 17 00:00:00 2001 From: Reed Allman Date: Sat, 13 Apr 2019 11:20:35 -0700 Subject: [PATCH 2/9] use buffer methods --- api/agent/func_logger.go | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/api/agent/func_logger.go b/api/agent/func_logger.go index 18f72a150e..43738f1e7e 100644 --- a/api/agent/func_logger.go +++ b/api/agent/func_logger.go @@ -103,20 +103,20 @@ func (li *lineWriter) Write(ogb []byte) (int, error) { } li.b.Write(ogb) // bytes.Buffer is guaranteed, read it! + var n int for { - b := li.b.Bytes() - i := bytes.IndexByte(b, '\n') - if i < 0 { - break // no more newlines in buffer + // read the line and advance buffer past it + l, err := li.b.ReadBytes('\n') + if err != nil { + break // no more newlines in buffer (see ReadBytes contract) } - // write in this line and advance buffer past it - l := b[:i+1] + // write in the line ns, err := li.w.Write(l) + n += ns if err != nil { - return ns, err + return n, err } - li.b.Next(len(l)) } // technically we wrote all the bytes, so make things appear normal From 42f119a878aa5bd42ad403c6157b6290e55b3f0a Mon Sep 17 00:00:00 2001 From: Reed Allman Date: Thu, 18 Apr 2019 00:16:34 -0700 Subject: [PATCH 3/9] continue the munging around, TODO figure out how to configure the env vars --- api/agent/agent.go | 14 ++++----- api/agent/agent_test.go | 59 ----------------------------------- api/agent/call.go | 17 +++++----- api/agent/config.go | 17 ++++------ api/agent/func_logger.go | 20 +++++++----- api/agent/lb_agent_test.go | 4 --- api/runnerpool/runner_pool.go | 1 - api/server/runner_fninvoke.go | 2 +- 8 files changed, 37 insertions(+), 97 deletions(-) diff --git a/api/agent/agent.go b/api/agent/agent.go index baa1f31135..b00176f6cb 100644 --- a/api/agent/agent.go +++ b/api/agent/agent.go @@ -1191,9 +1191,6 @@ func newHotContainer(ctx context.Context, evictor Evictor, call *call, cfg *Conf // have to be read or *BOTH* blocked consistently. In other words, we cannot block one and continue // reading from the other one without risking head-of-line blocking. - // TODO(reed): we should let the syslog driver pick this up really but our - // default story sucks there - // disable container logs if they're disabled on the call (pure_runner) - // users may use syslog to get container logs, unrelated to this writer. // otherwise, make a line writer and allow logrus DEBUG logs to host stderr @@ -1201,13 +1198,17 @@ func newHotContainer(ctx context.Context, evictor Evictor, call *call, cfg *Conf var bufs []*bytes.Buffer var stderr io.WriteCloser = call.stderr - if _, ok := stderr.(common.NoopReadWriteCloser); !ok { + if _, ok := stderr.(common.NoopReadWriteCloser); !ok && !cfg.DisableDebugUserLogs { gw := common.NewGhostWriter() buf1 := bufPool.Get().(*bytes.Buffer) - // TODO(reed): this logger may have garbage in it between calls, easy fix - // is to make a new one each swap, it's cheap enough to be doable. + // TODO(reed): this logger may have garbage in it between calls (without + // calling Close() to flush newlines, since we're swapping we can't), easy + // fix is to make a new one each swap, it's cheap enough to be doable. + // TODO(reed): we should only do this if they configure to log stderr, not if they use WithLogger(), + // for now use explicit disable with DisableDebugUserLogs sec := &nopCloser{newLogWriter( logrus.WithFields(logrus.Fields{"tag": "stderr", "app_id": call.AppID, "fn_id": call.FnID, "image": call.Image, "container_id": id}), + cfg.UserLogLevel, )} gw.Swap(newLineWriterWithBuffer(buf1, sec)) stderr = gw @@ -1338,7 +1339,6 @@ func (c *container) DisableNet() bool { return c.disableNet } func (c *container) WriteStat(ctx context.Context, stat driver_stats.Stat) { for key, value := range stat.Metrics { if m, ok := dockerMeasures[key]; ok { - common.Logger(ctx).WithField(key, value).Info("container stats") stats.Record(ctx, m.M(int64(value))) } } diff --git a/api/agent/agent_test.go b/api/agent/agent_test.go index 627743f015..5c1416eef1 100644 --- a/api/agent/agent_test.go +++ b/api/agent/agent_test.go @@ -275,65 +275,6 @@ func TestGetCallFromModelRoundTripACall(t *testing.T) { } } -func TestLoggerIsStringerAndWorks(t *testing.T) { - // TODO test limit writer, logrus writer, etc etc - - var call models.Call - logger := setupLogger(context.Background(), 1*1024*1024, true, &call) - - if _, ok := logger.(fmt.Stringer); !ok { - // NOTE: if you are reading, maybe what you've done is ok, but be aware we were relying on this for optimization... - t.Fatal("you turned the logger into something inefficient and possibly better all at the same time, how dare ye!") - } - - str := "0 line\n1 line\n2 line\n\n4 line" - logger.Write([]byte(str)) - - strGot := logger.(fmt.Stringer).String() - - if strGot != str { - t.Fatal("logs did not match expectations, like being an adult", strGot, str) - } - - logger.Close() // idk maybe this would panic might as well ca this - - // TODO we could check for the toilet to flush here to logrus -} - -func TestLoggerTooBig(t *testing.T) { - - var call models.Call - logger := setupLogger(context.Background(), 10, true, &call) - - str := fmt.Sprintf("0 line\n1 l\n-----max log size 10 bytes exceeded, truncating log-----\n") - - n, err := logger.Write([]byte(str)) - if err != nil { - t.Fatalf("err returned, but should not fail err=%v n=%d", err, n) - } - if n != len(str) { - t.Fatalf("n should be %d, but got=%d", len(str), n) - } - - // oneeeeee moreeee time... (cue in Daft Punk), the results appear as if we wrote - // again... But only "limit" bytes should succeed, ignoring the subsequent writes... - n, err = logger.Write([]byte(str)) - if err != nil { - t.Fatalf("err returned, but should not fail err=%v n=%d", err, n) - } - if n != len(str) { - t.Fatalf("n should be %d, but got=%d", len(str), n) - } - - strGot := logger.(fmt.Stringer).String() - - if strGot != str { - t.Fatalf("logs did not match expectations, like being an adult got=\n%v\nexpected=\n%v\n", strGot, str) - } - - logger.Close() -} - type testListener struct { afterCall func(context.Context, *models.Call) error } diff --git a/api/agent/call.go b/api/agent/call.go index 4ec2e20b41..a50186cc78 100644 --- a/api/agent/call.go +++ b/api/agent/call.go @@ -213,10 +213,17 @@ func WithDockerAuth(auth docker.Auther) CallOpt { } } -func (a *agent) WithStderrLogger() CallOpt { +// WithStderrLogger configures a call to have its container logs logged by fn. +// Configure UserLogLevel or DisableDebugUserLogs on agent to change behavior. +func WithStderrLogger() CallOpt { + // TODO(reed): we could take a context here which would allow request level logging vars on ctx to be used here too return func(c *call) error { - // XXX(reed): allow configuring the level / turning off - c.stderr = setupLogger(c.Call) + // TODO(reed): fucking hell this is a pain to configure + if a.cfg.DisableDebugUserLogs { + return nil + } + + c.stderr = setupLogger(a.cfg.UserLogLevel, c.Call) return nil } } @@ -328,10 +335,6 @@ func (c *call) ResponseWriter() http.ResponseWriter { return c.respWriter.(http.ResponseWriter) } -func (c *call) StdErr() io.ReadWriteCloser { - return c.stderr -} - func (c *call) AddUserExecutionTime(dur time.Duration) { if c.userExecTime == nil { c.userExecTime = new(time.Duration) diff --git a/api/agent/config.go b/api/agent/config.go index c0441cf743..7c9d73360c 100644 --- a/api/agent/config.go +++ b/api/agent/config.go @@ -42,6 +42,7 @@ type Config struct { MaxTmpFsInodes uint64 `json:"max_tmpfs_inodes"` DisableReadOnlyRootFs bool `json:"disable_readonly_rootfs"` DisableDebugUserLogs bool `json:"disable_debug_user_logs"` + UserLogLevel string `json:"user_log_level"` IOFSEnableTmpfs bool `json:"iofs_enable_tmpfs"` IOFSAgentPath string `json:"iofs_path"` IOFSMountRoot string `json:"iofs_mount_root"` @@ -73,16 +74,14 @@ const ( EnvHotPoll = "FN_HOT_POLL_MSECS" // EnvHotLauncherTimeout is the timeout for a hot container queue to persist if idle EnvHotLauncherTimeout = "FN_HOT_LAUNCHER_TIMEOUT_MSECS" - // EnvHotStartTimeout is the timeout for a hot container to be created including docker-pull + // EnvHotPullTimeout is the timeout for a hot container to be created including docker-pull EnvHotPullTimeout = "FN_HOT_PULL_TIMEOUT_MSECS" // EnvHotStartTimeout is the timeout for a hot container to become available for use for requests after EnvHotStartTimeout EnvHotStartTimeout = "FN_HOT_START_TIMEOUT_MSECS" // EnvMaxResponseSize is the maximum number of bytes that a function may return from an invocation EnvMaxResponseSize = "FN_MAX_RESPONSE_SIZE" - // EnvHdrMaxResponseSize is the maximum number of bytes that a function may return in an invocation header + // EnvMaxHdrResponseSize is the maximum number of bytes that a function may return in an invocation header EnvMaxHdrResponseSize = "FN_MAX_HDR_RESPONSE_SIZE" - // EnvMaxLogSize is the maximum size that a function's log may reach - EnvMaxLogSize = "FN_MAX_LOG_SIZE_BYTES" // EnvMaxTotalCPU is the maximum CPU that will be reserved across all containers EnvMaxTotalCPU = "FN_MAX_TOTAL_CPU_MCPUS" // EnvMaxTotalMemory is the maximum memory that will be reserved across all containers @@ -121,6 +120,8 @@ const ( EnvDisableReadOnlyRootFs = "FN_DISABLE_READONLY_ROOTFS" // EnvDisableDebugUserLogs disables user function logs being logged at level debug. wise to enable for production. EnvDisableDebugUserLogs = "FN_DISABLE_DEBUG_USER_LOGS" + // EnvUserLogLevel is the logging level to use for user's function logs to be logged by fn. to disable explicitly, use FN_DISABLE_DEBUG_USER_LOGS + EnvUserLogLevel = "FN_USER_LOG_LEVEL" // EnvIOFSEnableTmpfs enables creating a per-container tmpfs mount for the IOFS EnvIOFSEnableTmpfs = "FN_IOFS_TMPFS" @@ -155,7 +156,6 @@ const ( func NewConfig() (*Config, error) { cfg := &Config{ MinDockerVersion: "17.10.0-ce", - MaxLogSize: 1 * 1024 * 1024, PreForkImage: "busybox", PreForkCmd: "tail -f /dev/null", } @@ -175,7 +175,6 @@ func NewConfig() (*Config, error) { err = setEnvMsecs(err, EnvDetachedHeadroom, &cfg.DetachedHeadRoom, time.Duration(360)*time.Second) err = setEnvUint(err, EnvMaxResponseSize, &cfg.MaxResponseSize, nil) err = setEnvUint(err, EnvMaxHdrResponseSize, &cfg.MaxHdrResponseSize, nil) - err = setEnvUint(err, EnvMaxLogSize, &cfg.MaxLogSize, nil) err = setEnvUint(err, EnvMaxTotalCPU, &cfg.MaxTotalCPU, nil) err = setEnvUint(err, EnvMaxTotalMemory, &cfg.MaxTotalMemory, nil) err = setEnvUint(err, EnvMaxFsSize, &cfg.MaxFsSize, nil) @@ -201,6 +200,7 @@ func NewConfig() (*Config, error) { err = setEnvBool(err, EnvEnableNBResourceTracker, &cfg.EnableNBResourceTracker) err = setEnvBool(err, EnvDisableReadOnlyRootFs, &cfg.DisableReadOnlyRootFs) err = setEnvBool(err, EnvDisableDebugUserLogs, &cfg.DisableDebugUserLogs) + err = setEnvStr(err, EnvUserLogLevel, &cfg.UserLogLevel) err = setEnvUint(err, EnvImageCleanMaxSize, &cfg.ImageCleanMaxSize, nil) err = setEnvStr(err, EnvImageCleanExemptTags, &cfg.ImageCleanExemptTags) err = setEnvBool(err, EnvImageEnableVolume, &cfg.ImageEnableVolume) @@ -209,11 +209,6 @@ func NewConfig() (*Config, error) { return cfg, err } - if cfg.MaxLogSize > math.MaxInt64 { - // for safety during uint64 to int conversions in Write()/Read(), etc. - return cfg, fmt.Errorf("error invalid %s %v > %v", EnvMaxLogSize, cfg.MaxLogSize, math.MaxInt64) - } - return cfg, nil } diff --git a/api/agent/func_logger.go b/api/agent/func_logger.go index 43738f1e7e..6ea7df38b8 100644 --- a/api/agent/func_logger.go +++ b/api/agent/func_logger.go @@ -15,7 +15,7 @@ var ( ) // * [always] writes bytes per line to stderr as DEBUG -func setupLogger(c *models.Call) io.WriteCloser { +func setupLogger(level string, c *models.Call) io.WriteCloser { lbuf := bufPool.Get().(*bytes.Buffer) close := func() { @@ -25,7 +25,7 @@ func setupLogger(c *models.Call) io.WriteCloser { } stderrLogger := logrus.WithFields(logrus.Fields{"user_log": true, "app_id": c.AppID, "fn_id": c.FnID, "image": c.Image, "call_id": c.ID}) - loggo := newLogWriter(stderrLogger) + loggo := newLogWriter(stderrLogger, level) linew := newLineWriterWithBuffer(lbuf, loggo) linew = &fCloser{ close: func() error { @@ -54,13 +54,19 @@ func (n *nopCloser) Close() error { return nil } // logWriter will log (to real stderr) every call to Write as a line. it should // be wrapped with a lineWriter so that the output makes sense. type logWriter struct { - // level string // XXX(reed): - logrus.FieldLogger + level logrus.Level + logger logrus.FieldLogger closed uint32 } -func newLogWriter(logger logrus.FieldLogger) io.WriteCloser { - return &logWriter{FieldLogger: logger} +func newLogWriter(logger logrus.FieldLogger, level string) io.WriteCloser { + lv, err := logrus.ParseLevel(level) + if err != nil { + // TODO(reed): we should do this at the config level instead? it's an optional option to begin with tho (StderrLogger) + lv = logrus.InfoLevel // default + } + + return &logWriter{logger: logger, level: lv} } func (l *logWriter) Write(b []byte) (int, error) { @@ -68,7 +74,7 @@ func (l *logWriter) Write(b []byte) (int, error) { // we don't want to return 0/error or the container will get shut down return len(b), nil } - l.Debug(string(b)) + l.logger.WithFields(nil).Log(l.level, string(b)) return len(b), nil } diff --git a/api/agent/lb_agent_test.go b/api/agent/lb_agent_test.go index 14b6a279c6..b8b20ce468 100644 --- a/api/agent/lb_agent_test.go +++ b/api/agent/lb_agent_test.go @@ -125,10 +125,6 @@ func (c *mockRunnerCall) ResponseWriter() http.ResponseWriter { return c.rw } -func (c *mockRunnerCall) StdErr() io.ReadWriteCloser { - return c.stdErr -} - func (c *mockRunnerCall) Model() *models.Call { return c.model } diff --git a/api/runnerpool/runner_pool.go b/api/runnerpool/runner_pool.go index 1e2bcda94d..12b3b7f983 100644 --- a/api/runnerpool/runner_pool.go +++ b/api/runnerpool/runner_pool.go @@ -59,7 +59,6 @@ type RunnerCall interface { Extensions() map[string]string RequestBody() io.ReadCloser ResponseWriter() http.ResponseWriter - StdErr() io.ReadWriteCloser Model() *models.Call // For metrics/stats, add special accounting for time spent in customer code AddUserExecutionTime(dur time.Duration) diff --git a/api/server/runner_fninvoke.go b/api/server/runner_fninvoke.go index cf249898fc..06931d1b0d 100644 --- a/api/server/runner_fninvoke.go +++ b/api/server/runner_fninvoke.go @@ -109,7 +109,7 @@ func (s *Server) fnInvoke(resp http.ResponseWriter, req *http.Request, app *mode } } - opts = append(opts, agent.WithWriter(rw)) + opts = append(opts, agent.WithWriter(writer)) opts = append(opts, agent.WithStderrLogger()) if trig != nil { opts = append(opts, agent.WithTrigger(trig)) From 3b173a5ad4452e21b312c4100ed8be69380efc76 Mon Sep 17 00:00:00 2001 From: Reed Allman Date: Thu, 18 Apr 2019 00:16:47 -0700 Subject: [PATCH 4/9] update logrus --- go.mod | 2 +- go.sum | 59 +- .../exec_runner_status_test.go | 1 - vendor/github.com/sirupsen/logrus/.travis.yml | 65 +- .../github.com/sirupsen/logrus/CHANGELOG.md | 33 + vendor/github.com/sirupsen/logrus/README.md | 1 + vendor/github.com/sirupsen/logrus/alt_exit.go | 18 +- vendor/github.com/sirupsen/logrus/entry.go | 32 +- vendor/github.com/sirupsen/logrus/exported.go | 6 + vendor/github.com/sirupsen/logrus/go.mod | 1 - vendor/github.com/sirupsen/logrus/go.sum | 2 - .../sirupsen/logrus/json_formatter.go | 22 +- vendor/github.com/sirupsen/logrus/logger.go | 12 +- vendor/github.com/sirupsen/logrus/logrus.go | 2 +- .../sirupsen/logrus/terminal_check_aix.go | 9 - .../sirupsen/logrus/terminal_check_bsd.go | 13 + .../logrus/terminal_check_notappengine.go | 6 +- .../sirupsen/logrus/terminal_check_unix.go | 13 + .../sirupsen/logrus/text_formatter.go | 60 +- vendor/golang.org/x/crypto/AUTHORS | 3 - vendor/golang.org/x/crypto/CONTRIBUTORS | 3 - vendor/golang.org/x/crypto/LICENSE | 27 - vendor/golang.org/x/crypto/PATENTS | 22 - .../x/crypto/ssh/terminal/terminal.go | 955 ------------------ .../golang.org/x/crypto/ssh/terminal/util.go | 114 --- .../x/crypto/ssh/terminal/util_aix.go | 12 - .../x/crypto/ssh/terminal/util_bsd.go | 12 - .../x/crypto/ssh/terminal/util_linux.go | 10 - .../x/crypto/ssh/terminal/util_plan9.go | 58 -- .../x/crypto/ssh/terminal/util_solaris.go | 124 --- .../x/crypto/ssh/terminal/util_windows.go | 105 -- vendor/modules.txt | 4 +- 32 files changed, 200 insertions(+), 1606 deletions(-) delete mode 100644 vendor/github.com/sirupsen/logrus/terminal_check_aix.go create mode 100644 vendor/github.com/sirupsen/logrus/terminal_check_bsd.go create mode 100644 vendor/github.com/sirupsen/logrus/terminal_check_unix.go delete mode 100644 vendor/golang.org/x/crypto/AUTHORS delete mode 100644 vendor/golang.org/x/crypto/CONTRIBUTORS delete mode 100644 vendor/golang.org/x/crypto/LICENSE delete mode 100644 vendor/golang.org/x/crypto/PATENTS delete mode 100644 vendor/golang.org/x/crypto/ssh/terminal/terminal.go delete mode 100644 vendor/golang.org/x/crypto/ssh/terminal/util.go delete mode 100644 vendor/golang.org/x/crypto/ssh/terminal/util_aix.go delete mode 100644 vendor/golang.org/x/crypto/ssh/terminal/util_bsd.go delete mode 100644 vendor/golang.org/x/crypto/ssh/terminal/util_linux.go delete mode 100644 vendor/golang.org/x/crypto/ssh/terminal/util_plan9.go delete mode 100644 vendor/golang.org/x/crypto/ssh/terminal/util_solaris.go delete mode 100644 vendor/golang.org/x/crypto/ssh/terminal/util_windows.go diff --git a/go.mod b/go.mod index c084b67161..d1136f3a6d 100644 --- a/go.mod +++ b/go.mod @@ -26,7 +26,7 @@ require ( github.com/openzipkin/zipkin-go v0.1.3 github.com/patrickmn/go-cache v2.1.0+incompatible github.com/prometheus/client_golang v0.9.2 - github.com/sirupsen/logrus v1.3.0 + github.com/sirupsen/logrus v1.4.1 github.com/ugorji/go/codec v0.0.0-20181022190402-e5e69e061d4f // indirect go.opencensus.io v0.19.0 golang.org/x/net v0.0.0-20181217023233-e147a9138326 diff --git a/go.sum b/go.sum index ee8151c821..9b2ae282e2 100644 --- a/go.sum +++ b/go.sum @@ -4,56 +4,37 @@ git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGy git.apache.org/thrift.git v0.0.0-20181218151757-9b75e4fe745a h1:GnKpWvJXysBGdcWMEibN//UeRRJeLDUgsXjKXjagFLg= git.apache.org/thrift.git v0.0.0-20181218151757-9b75e4fe745a/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg= github.com/GoogleCloudPlatform/cloudsql-proxy v0.0.0-20181009230506-ac834ce67862/go.mod h1:aJ4qN3TfrelA6NZ6AXsXRfmEVaYin3EDbSPJrKS8OXo= -github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw= -github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk= github.com/aws/aws-sdk-go v1.15.27/go.mod h1:mFuSZ37Z9YOHbQEwBWztmVzqXrEkub65tZoCYDt7FT0= github.com/aws/aws-sdk-go v1.15.57/go.mod h1:mFuSZ37Z9YOHbQEwBWztmVzqXrEkub65tZoCYDt7FT0= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 h1:xJ4a3vCFaGF/jqvzLMYoU8P317H5OQ+Via4RmuPwCS0= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/containerd/continuity v0.0.0-20181001140422-bd77b46c8352/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= -github.com/containerd/continuity v0.0.0-20181003075958-be9bd761db19 h1:HSgjWPBWohO3kHDPwCPUGSLqJjXCjA7ad5057beR2ZU= -github.com/containerd/continuity v0.0.0-20181003075958-be9bd761db19/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= github.com/containerd/continuity v0.0.0-20181203112020-004b46473808 h1:4BX8f882bXEDKfWIf0wa8HRvpnBoPszJJXL+TVbBw4M= github.com/containerd/continuity v0.0.0-20181203112020-004b46473808/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= -github.com/coreos/bbolt v1.3.1-coreos.6 h1:uTXKg9gY70s9jMAKdfljFQcuh4e/BXOM+V+d00KFj3A= github.com/coreos/bbolt v1.3.1-coreos.6/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= -github.com/coreos/etcd v3.3.10+incompatible h1:jFneRYjIvLMLhDLCzuTuU4rSJUjRplcJQ7pD7MnhC04= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-semver v0.2.1-0.20180108230905-e214231b295a h1:U0BbGfKnviqVBJQB4etvm+mKx53KfkumNLBt6YeF/0Q= github.com/coreos/go-semver v0.2.1-0.20180108230905-e214231b295a/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= -github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d h1:t5Wuyh53qYyg9eqn4BbnlIT+vmhyww0TatL+zT3uWgI= github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f h1:lBNOc5arjvs8E5mO2tbpBpLoyyu8B6e44T7hJy6potg= github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dchest/siphash v1.2.0 h1:YWOShuhvg0GqbQpMa60QlCGtEyf7O7HC1Jf0VjdQ60M= github.com/dchest/siphash v1.2.0/go.mod h1:q+IRvb2gOSrUnYoPqHiyHXS0FOBBOdl6tONBlVnOnt4= -github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dnaeon/go-vcr v0.0.0-20180920040454-5637cf3d8a31/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E= -github.com/docker/docker v0.7.3-0.20180827131323-0c5f8d2b9b23/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= -github.com/docker/docker v0.7.3-0.20180904180028-c3e32938430e h1:kP94wkOn/rE/8uZ0xh4B+4cz1TTHyVMZ6cx5p0m2Yjo= -github.com/docker/docker v0.7.3-0.20180904180028-c3e32938430e/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker v0.7.3-0.20190309235953-33c3200e0d16 h1:dmUn0SuGx7unKFwxyeQ/oLUHhEfZosEDrpmYM+6MTuc= github.com/docker/docker v0.7.3-0.20190309235953-33c3200e0d16/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= github.com/docker/go-units v0.3.3 h1:Xk8S3Xj5sLGlG5g67hJmYMmUgXv5N4PhkjJHHqrwnTk= github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= -github.com/docker/libnetwork v0.8.0-dev.2.0.20180608203834-19279f049241 h1:+ebE/hCU02srkeIg8Vp/vlUp182JapYWtXzV+bCeR2I= -github.com/docker/libnetwork v0.8.0-dev.2.0.20180608203834-19279f049241/go.mod h1:93m0aTqz6z+g32wla4l4WxTrdtvBRmVzYRkYvasA5Z8= github.com/fnproject/fdk-go v0.0.0-20181025170718-26ed643bea68 h1:T1Lm0ByviRKOUocQfjkVJ8EtinhJYwGVaoTQa2XVET0= github.com/fnproject/fdk-go v0.0.0-20181025170718-26ed643bea68/go.mod h1:hzkP3qqXx+1pRBh2QVKr1I+jJ+5xrHIlh5z59XKZ/k0= github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/fsouza/go-dockerclient v1.3.2-0.20181102000906-311c4469e611 h1:IJeFPHY397zestvlrZU6gPqXYcqbdCv5ozgKrDw23vc= -github.com/fsouza/go-dockerclient v1.3.2-0.20181102000906-311c4469e611/go.mod h1:2TeM+/lPmwJT5CDBQ4vBpHJ0LAZ5p+Qquwp2dDN89eA= github.com/fsouza/go-dockerclient v1.4.0 h1:Fhqy7UOYW+4ILvC3dtiY3Jzr3XXSSrbq56IhTPxkMnE= github.com/fsouza/go-dockerclient v1.4.0/go.mod h1:GmPog78dvaRLJqt7QU7fRLaJKUkYW2hYjxKCp1uwGwE= -github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/gin-contrib/cors v0.0.0-20170318125340-cf4846e6a636 h1:oGgJA7DJphAc81EMHZ+2G7Ai2xyg5eoq7bbqzCsiWFc= github.com/gin-contrib/cors v0.0.0-20170318125340-cf4846e6a636/go.mod h1:cw+u9IsAkC16e42NtYYVCLsHYXE98nB3M7Dr9mLSeH4= @@ -65,11 +46,9 @@ github.com/go-ini/ini v1.25.4/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3I github.com/go-ini/ini v1.39.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8= github.com/go-sql-driver/mysql v1.4.0 h1:7LxgVwFb2hIQtMm87NdgAVfXjnt4OePseqT1tKx+opk= github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= -github.com/gogo/protobuf v1.1.1 h1:72R+M5VuhED/KujmZVcIquuo8mBgX4oVda//DQb3PXo= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.1 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20180924190550-6f2cf27854a4 h1:6UVLWz0fIIrv0UVj6t0A7cL48n8IyAdLVQqAYzEfsKI= github.com/golang/groupcache v0.0.0-20180924190550-6f2cf27854a4/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -80,27 +59,20 @@ github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5y github.com/golang/protobuf v1.3.0/go.mod h1:Qd/q+1AKNOZr9uGQzbzCmRO6sUih6GTPZv6a1/R87v0= github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c h1:964Od4U6p2jUkFxvCydnIczKteheJEzHRToSGK3Bnlw= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/go-cloud v0.4.1-0.20181025204856-f29236cc19de/go.mod h1:zIXR03PyBRhLPWwHYkj98zq25qmUVwn1NL8GZB/+lF8= -github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= -github.com/gorilla/context v1.1.1 h1:AWwleXJkX/nhcU9bZSnZoi3h/qGYqQAGhq6zZe/aQW8= github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= -github.com/gorilla/mux v1.6.2 h1:Pgr17XVTNXAk3q/r4CpKzC5xBM/qW1uVLV+IhRZpIIk= github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/mux v1.7.1/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= -github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q= github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/grpc-ecosystem/go-grpc-middleware v1.0.0 h1:Iju5GlWwrvL6UBg4zJJt3btmonfrMlCDdsejg4CZE7c= github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= -github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= github.com/grpc-ecosystem/grpc-gateway v1.5.1/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw= -github.com/grpc-ecosystem/grpc-gateway v1.6.2 h1:8KyC64BiO8ndiGHY5DlFWWdangUPC9QHPakFRre/Ud0= github.com/grpc-ecosystem/grpc-gateway v1.6.2/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw= github.com/ijc/Gotty v0.0.0-20170406111628-a8b993ba6abd h1:anPrsicrIi2ColgWTVPk+TrN42hJIWlfPHSBP9S0ZkM= github.com/ijc/Gotty v0.0.0-20170406111628-a8b993ba6abd/go.mod h1:3LVOLeyx9XVvwPgrt2be44XgSqndprz1G18rSk8KD84= @@ -108,7 +80,6 @@ github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jmoiron/sqlx v1.2.0 h1:41Ip0zITnmWNR/vHV+S4m+VoUivnWY5E4OJfLZjCJMA= github.com/jmoiron/sqlx v1.2.0/go.mod h1:1FEQNm3xlJgrMD+FBdI9+xvCksHtbpVBBw5dYhBSsks= -github.com/jonboulle/clockwork v0.1.0 h1:VKV+ZcuP6l3yW9doeqz6ziZGgcynBVQO+obU0+0hcPo= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/json-iterator/go v1.1.5 h1:gL2yXlmiIo4+t+y32d4WGwOjKGYcGOuyrg46vadswDE= github.com/json-iterator/go v1.1.5/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= @@ -118,10 +89,8 @@ github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+o github.com/konsorten/go-windows-terminal-sequences v0.0.0-20180402223658-b729f2633dfe/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/leanovate/gopter v0.2.2 h1:3xTdawAVXlqePkgram0u+w6aMFn1RmOLbjzsI32jwp0= github.com/leanovate/gopter v0.2.2/go.mod h1:gNcbPWNEWRe4lm+bycKqxUYoH5uoVje5SkOJ3uoLer8= @@ -149,11 +118,9 @@ github.com/openzipkin/zipkin-go v0.1.3 h1:36hTtUTQR/vPX7YVJo2PYexSbHdAJiAkDrjuXw github.com/openzipkin/zipkin-go v0.1.3/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8= github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc= github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ= -github.com/pkg/errors v0.8.0 h1:WdK/asTD0HN+q6hsWO3/vpuAkAr+tw6aNJNDFFf0+qw= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= @@ -170,44 +137,29 @@ github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a h1:9a8MnZMP0X2nLJdBg+pBmGgkJlSaKC2KaQmTCk1XDtE= github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/sirupsen/logrus v1.1.0/go.mod h1:zrgwTnHtNr00buQ1vSptGe8m1f/BbgsPukg8qsT7A+A= -github.com/sirupsen/logrus v1.1.1 h1:VzGj7lhU7KEB9e9gMpAV/v5XT2NVSvLJhJLCWbnkgXg= github.com/sirupsen/logrus v1.1.1/go.mod h1:zrgwTnHtNr00buQ1vSptGe8m1f/BbgsPukg8qsT7A+A= -github.com/sirupsen/logrus v1.3.0 h1:hI/7Q+DtNZ2kINb6qt/lS+IyXnHQe9e90POfeewL/ME= github.com/sirupsen/logrus v1.3.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/sirupsen/logrus v1.4.1 h1:GL2rEmy6nsikmW0r8opw9JIRScdMF5hA8cOYLH7In1k= +github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v0.0.0-20180222194500-ef6db91d284a/go.mod h1:XDJAKZRPZ1CvBcN2aX5YOUTYGHki24fSF0Iv48Ibg0s= -github.com/soheilhy/cmux v0.1.4 h1:0HKaf1o97UwFjHH9o5XsHUOF+tqmdA7KEzXLpiyaw0E= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/tmc/grpc-websocket-proxy v0.0.0-20171017195756-830351dc03c6 h1:lYIiVDtZnyTWlNwiAxLj0bbpTcx1BWCFhXjfsvmPdNc= github.com/tmc/grpc-websocket-proxy v0.0.0-20171017195756-830351dc03c6/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/ugorji/go/codec v0.0.0-20181012064053-8333dd449516/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= github.com/ugorji/go/codec v0.0.0-20181022190402-e5e69e061d4f h1:y3Vj7GoDdcBkxFa2RUUFKM25TrBbWVDnjRDI0u975zQ= github.com/ugorji/go/codec v0.0.0-20181022190402-e5e69e061d4f/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= -github.com/vishvananda/netlink v1.0.0 h1:bqNY2lgheFIu1meHUFSH3d7vG93AFyqg3oGbJCOJgSM= -github.com/vishvananda/netlink v1.0.0/go.mod h1:+SR5DhBJrl6ZM7CoCKvpw5BKroDKQ+PJqOg65H/2ktk= -github.com/vishvananda/netns v0.0.0-20180720170159-13995c7128cc h1:R83G5ikgLMxrBvLh22JhdfI8K6YXEPHx5P03Uu3DRs4= -github.com/vishvananda/netns v0.0.0-20180720170159-13995c7128cc/go.mod h1:ZjcWmFBXmLKZu9Nxj3WKYEafiSqer2rnvPr0en9UNpI= -github.com/xiang90/probing v0.0.0-20160813154853-07dd2e8dfe18 h1:MPPkRncZLN9Kh4MEFmbnK4h3BD7AUmskWv2+EeZJCCs= github.com/xiang90/probing v0.0.0-20160813154853-07dd2e8dfe18/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= go.opencensus.io v0.15.0/go.mod h1:UffZAU+4sDEINUGP/B7UfBBkq4fqLu9zXAX7ke6CHW0= go.opencensus.io v0.17.0/go.mod h1:mp1VrMQxhlqqDpKvH4UcQUa4YwlzNmymAjPrDdfxNpI= go.opencensus.io v0.19.0 h1:+jrnNy8MR4GZXvwF9PEuSyHxA4NaTf6601oNRwCSXq0= go.opencensus.io v0.19.0/go.mod h1:AYeH0+ZxYyghG8diqaaIq/9P3VgCCt5GF2ldCY4dkFg= -go.uber.org/atomic v1.3.2 h1:2Oa65PReHzfn29GpvgsYwloV9AVFHPDk8tYxt2c2tr4= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= -go.uber.org/multierr v1.1.0 h1:HoEmRHQPVSqub6w2z2d2EOVs2fjyFRGyofhKuyDq0QI= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= -go.uber.org/zap v1.9.1 h1:XCJQEf3W6eZaVwhRBof6ImoYGJSITeKWsyeh3HFu/5o= go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20181001203147-e3636079e1a4/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20181015023909-0c41d7ab0a0e h1:IzypfodbhbnViNUO/MEh0FzCUooG97cIGfdggUrUSyU= golang.org/x/crypto v0.0.0-20181015023909-0c41d7ab0a0e/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -224,16 +176,13 @@ golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAG golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181108010431-42b317875d0f h1:Bl/8QSvNqXvPGPGXa2z5xUTmV7VDcZyvRZ+QQXkXTZQ= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4 h1:YUO/7uOKsKeq9UokNS62b8FYywz3ker1l1vDZRCRefw= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180928133829-e4b3c5e90611/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181011152604-fa43e7bc11ba/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181218192612-074acd46bca6 h1:MXtOG7w2ND9qNCUZSDBGll/SpVIq7ftozR9I8/JGBHY= golang.org/x/sys v0.0.0-20181218192612-074acd46bca6/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190310054646-10058d7d4faa h1:lqti/xP+yD/6zH5TqEwx2MilNIJY5Vbc6Qr8J3qyPIQ= @@ -265,9 +214,7 @@ google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9M google.golang.org/grpc v1.17.0 h1:TRJYBgMclJvGYn2rIMjj+h9KtMt5r1Ij7ODVRIZkwhk= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/go-playground/assert.v1 v1.2.1 h1:xoYuJVE7KT85PYWrN730RguIQO0ePzVRfFMXadIrXTM= gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE= gopkg.in/go-playground/validator.v8 v8.18.2 h1:lFB4DoMU6B626w8ny76MV7VX6W2VHct2GVOI3xgiMrQ= gopkg.in/go-playground/validator.v8 v8.18.2/go.mod h1:RX2a/7Ha8BgOhfk7j780h4/u/RRjR0eouCJSH80/M2Y= @@ -276,8 +223,6 @@ gopkg.in/pipe.v2 v2.0.0-20140414041502-3c2ca4d52544/go.mod h1:UhTeH/yXCK/KY7TX24 gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gotest.tools v2.1.0+incompatible h1:5USw7CrJBYKqjg9R7QlA6jzqZKEAtvW82aNmsxxGPxw= -gotest.tools v2.1.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20180920025451-e3ad64cb4ed3/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/test/fn-system-tests/exec_runner_status_test.go b/test/fn-system-tests/exec_runner_status_test.go index 64eadae0e1..9063747e55 100644 --- a/test/fn-system-tests/exec_runner_status_test.go +++ b/test/fn-system-tests/exec_runner_status_test.go @@ -103,7 +103,6 @@ func (c *myCall) SlotHashId() string { return "" } func (c *myCall) Extensions() map[string]string { return nil } func (c *myCall) RequestBody() io.ReadCloser { return nil } func (c *myCall) ResponseWriter() http.ResponseWriter { return nil } -func (c *myCall) StdErr() io.ReadWriteCloser { return nil } func (c *myCall) Model() *models.Call { return nil } func (c *myCall) GetUserExecutionTime() *time.Duration { return nil } func (c *myCall) AddUserExecutionTime(time.Duration) {} diff --git a/vendor/github.com/sirupsen/logrus/.travis.yml b/vendor/github.com/sirupsen/logrus/.travis.yml index a8f1545158..7e54dc6e3b 100644 --- a/vendor/github.com/sirupsen/logrus/.travis.yml +++ b/vendor/github.com/sirupsen/logrus/.travis.yml @@ -1,52 +1,21 @@ language: go go_import_path: github.com/sirupsen/logrus +git: + depth: 1 env: - - GOMAXPROCS=4 GORACE=halt_on_error=1 + - GO111MODULE=on + - GO111MODULE=off +go: [ 1.10.x, 1.11.x, 1.12.x ] +os: [ linux, osx, windows ] matrix: - include: - - go: 1.10.x - install: - - go get github.com/stretchr/testify/assert - - go get golang.org/x/crypto/ssh/terminal - - go get golang.org/x/sys/unix - - go get golang.org/x/sys/windows - script: - - go test -race -v ./... - - go: 1.11.x - env: GO111MODULE=on - install: - - go mod download - script: - - go test -race -v ./... - - go: 1.11.x - env: GO111MODULE=off - install: - - go get github.com/stretchr/testify/assert - - go get golang.org/x/crypto/ssh/terminal - - go get golang.org/x/sys/unix - - go get golang.org/x/sys/windows - script: - - go test -race -v ./... - - go: 1.10.x - install: - - go get github.com/stretchr/testify/assert - - go get golang.org/x/crypto/ssh/terminal - - go get golang.org/x/sys/unix - - go get golang.org/x/sys/windows - script: - - go test -race -v -tags appengine ./... - - go: 1.11.x - env: GO111MODULE=on - install: - - go mod download - script: - - go test -race -v -tags appengine ./... - - go: 1.11.x - env: GO111MODULE=off - install: - - go get github.com/stretchr/testify/assert - - go get golang.org/x/crypto/ssh/terminal - - go get golang.org/x/sys/unix - - go get golang.org/x/sys/windows - script: - - go test -race -v -tags appengine ./... + exclude: + - env: GO111MODULE=on + go: 1.10.x +install: + - if [[ "$GO111MODULE" == "on" ]]; then go mod download; fi + - if [[ "$GO111MODULE" == "off" ]]; then go get github.com/stretchr/testify/assert golang.org/x/sys/unix github.com/konsorten/go-windows-terminal-sequences; fi +script: + - export GOMAXPROCS=4 + - export GORACE=halt_on_error=1 + - go test -race -v ./... + - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then go test -race -v -tags appengine ./... ; fi diff --git a/vendor/github.com/sirupsen/logrus/CHANGELOG.md b/vendor/github.com/sirupsen/logrus/CHANGELOG.md index cb85d9f9f6..f62cbd24a7 100644 --- a/vendor/github.com/sirupsen/logrus/CHANGELOG.md +++ b/vendor/github.com/sirupsen/logrus/CHANGELOG.md @@ -1,3 +1,36 @@ +# 1.4.1 +This new release introduces: + * Enhance TextFormatter to not print caller information when they are empty (#944) + * Remove dependency on golang.org/x/crypto (#932, #943) + +Fixes: + * Fix Entry.WithContext method to return a copy of the initial entry (#941) + +# 1.4.0 +This new release introduces: + * Add `DeferExitHandler`, similar to `RegisterExitHandler` but prepending the handler to the list of handlers (semantically like `defer`) (#848). + * Add `CallerPrettyfier` to `JSONFormatter` and `TextFormatter (#909, #911) + * Add `Entry.WithContext()` and `Entry.Context`, to set a context on entries to be used e.g. in hooks (#919). + +Fixes: + * Fix wrong method calls `Logger.Print` and `Logger.Warningln` (#893). + * Update `Entry.Logf` to not do string formatting unless the log level is enabled (#903) + * Fix infinite recursion on unknown `Level.String()` (#907) + * Fix race condition in `getCaller` (#916). + + +# 1.3.0 +This new release introduces: + * Log, Logf, Logln functions for Logger and Entry that take a Level + +Fixes: + * Building prometheus node_exporter on AIX (#840) + * Race condition in TextFormatter (#468) + * Travis CI import path (#868) + * Remove coloured output on Windows (#862) + * Pointer to func as field in JSONFormatter (#870) + * Properly marshal Levels (#873) + # 1.2.0 This new release introduces: * A new method `SetReportCaller` in the `Logger` to enable the file, line and calling function from which the trace has been issued diff --git a/vendor/github.com/sirupsen/logrus/README.md b/vendor/github.com/sirupsen/logrus/README.md index 3987310551..a4796eb07d 100644 --- a/vendor/github.com/sirupsen/logrus/README.md +++ b/vendor/github.com/sirupsen/logrus/README.md @@ -365,6 +365,7 @@ Third party logging formatters: * [`logstash`](https://github.com/bshuster-repo/logrus-logstash-hook). Logs fields as [Logstash](http://logstash.net) Events. * [`prefixed`](https://github.com/x-cray/logrus-prefixed-formatter). Displays log entry source along with alternative layout. * [`zalgo`](https://github.com/aybabtme/logzalgo). Invoking the P͉̫o̳̼̊w̖͈̰͎e̬͔̭͂r͚̼̹̲ ̫͓͉̳͈ō̠͕͖̚f̝͍̠ ͕̲̞͖͑Z̖̫̤̫ͪa͉̬͈̗l͖͎g̳̥o̰̥̅!̣͔̲̻͊̄ ̙̘̦̹̦. +* [`nested-logrus-formatter`](https://github.com/antonfisher/nested-logrus-formatter). Converts logrus fields to a nested structure. You can define your formatter by implementing the `Formatter` interface, requiring a `Format` method. `Format` takes an `*Entry`. `entry.Data` is a diff --git a/vendor/github.com/sirupsen/logrus/alt_exit.go b/vendor/github.com/sirupsen/logrus/alt_exit.go index 8af90637a9..8fd189e1cc 100644 --- a/vendor/github.com/sirupsen/logrus/alt_exit.go +++ b/vendor/github.com/sirupsen/logrus/alt_exit.go @@ -51,9 +51,9 @@ func Exit(code int) { os.Exit(code) } -// RegisterExitHandler adds a Logrus Exit handler, call logrus.Exit to invoke -// all handlers. The handlers will also be invoked when any Fatal log entry is -// made. +// RegisterExitHandler appends a Logrus Exit handler to the list of handlers, +// call logrus.Exit to invoke all handlers. The handlers will also be invoked when +// any Fatal log entry is made. // // This method is useful when a caller wishes to use logrus to log a fatal // message but also needs to gracefully shutdown. An example usecase could be @@ -62,3 +62,15 @@ func Exit(code int) { func RegisterExitHandler(handler func()) { handlers = append(handlers, handler) } + +// DeferExitHandler prepends a Logrus Exit handler to the list of handlers, +// call logrus.Exit to invoke all handlers. The handlers will also be invoked when +// any Fatal log entry is made. +// +// This method is useful when a caller wishes to use logrus to log a fatal +// message but also needs to gracefully shutdown. An example usecase could be +// closing database connections, or sending a alert that the application is +// closing. +func DeferExitHandler(handler func()) { + handlers = append([]func(){handler}, handlers...) +} diff --git a/vendor/github.com/sirupsen/logrus/entry.go b/vendor/github.com/sirupsen/logrus/entry.go index df6d188def..63e25583cb 100644 --- a/vendor/github.com/sirupsen/logrus/entry.go +++ b/vendor/github.com/sirupsen/logrus/entry.go @@ -2,6 +2,7 @@ package logrus import ( "bytes" + "context" "fmt" "os" "reflect" @@ -69,6 +70,9 @@ type Entry struct { // When formatter is called in entry.log(), a Buffer may be set to entry Buffer *bytes.Buffer + // Contains the context set by the user. Useful for hook processing etc. + Context context.Context + // err may contain a field formatting error err string } @@ -97,6 +101,11 @@ func (entry *Entry) WithError(err error) *Entry { return entry.WithField(ErrorKey, err) } +// Add a context to the Entry. +func (entry *Entry) WithContext(ctx context.Context) *Entry { + return &Entry{Logger: entry.Logger, Data: entry.Data, Time: entry.Time, err: entry.err, Context: ctx} +} + // Add a single field to the Entry. func (entry *Entry) WithField(key string, value interface{}) *Entry { return entry.WithFields(Fields{key: value}) @@ -130,12 +139,12 @@ func (entry *Entry) WithFields(fields Fields) *Entry { data[k] = v } } - return &Entry{Logger: entry.Logger, Data: data, Time: entry.Time, err: fieldErr} + return &Entry{Logger: entry.Logger, Data: data, Time: entry.Time, err: fieldErr, Context: entry.Context} } // Overrides the time of the Entry. func (entry *Entry) WithTime(t time.Time) *Entry { - return &Entry{Logger: entry.Logger, Data: entry.Data, Time: t, err: entry.err} + return &Entry{Logger: entry.Logger, Data: entry.Data, Time: t, err: entry.err, Context: entry.Context} } // getPackageName reduces a fully qualified function name to the package name @@ -156,20 +165,23 @@ func getPackageName(f string) string { // getCaller retrieves the name of the first non-logrus calling function func getCaller() *runtime.Frame { - // Restrict the lookback frames to avoid runaway lookups - pcs := make([]uintptr, maximumCallerDepth) - depth := runtime.Callers(minimumCallerDepth, pcs) - frames := runtime.CallersFrames(pcs[:depth]) // cache this package's fully-qualified name callerInitOnce.Do(func() { - logrusPackage = getPackageName(runtime.FuncForPC(pcs[0]).Name()) + pcs := make([]uintptr, 2) + _ = runtime.Callers(0, pcs) + logrusPackage = getPackageName(runtime.FuncForPC(pcs[1]).Name()) // now that we have the cache, we can skip a minimum count of known-logrus functions - // XXX this is dubious, the number of frames may vary store an entry in a logger interface + // XXX this is dubious, the number of frames may vary minimumCallerDepth = knownLogrusFrames }) + // Restrict the lookback frames to avoid runaway lookups + pcs := make([]uintptr, maximumCallerDepth) + depth := runtime.Callers(minimumCallerDepth, pcs) + frames := runtime.CallersFrames(pcs[:depth]) + for f, again := frames.Next(); again; f, again = frames.Next() { pkg := getPackageName(f.Function) @@ -298,7 +310,9 @@ func (entry *Entry) Panic(args ...interface{}) { // Entry Printf family functions func (entry *Entry) Logf(level Level, format string, args ...interface{}) { - entry.Log(level, fmt.Sprintf(format, args...)) + if entry.Logger.IsLevelEnabled(level) { + entry.Log(level, fmt.Sprintf(format, args...)) + } } func (entry *Entry) Tracef(format string, args ...interface{}) { diff --git a/vendor/github.com/sirupsen/logrus/exported.go b/vendor/github.com/sirupsen/logrus/exported.go index 7342613c37..62fc2f2193 100644 --- a/vendor/github.com/sirupsen/logrus/exported.go +++ b/vendor/github.com/sirupsen/logrus/exported.go @@ -1,6 +1,7 @@ package logrus import ( + "context" "io" "time" ) @@ -55,6 +56,11 @@ func WithError(err error) *Entry { return std.WithField(ErrorKey, err) } +// WithContext creates an entry from the standard logger and adds a context to it. +func WithContext(ctx context.Context) *Entry { + return std.WithContext(ctx) +} + // WithField creates an entry from the standard logger and adds a field to // it. If you want multiple fields, use `WithFields`. // diff --git a/vendor/github.com/sirupsen/logrus/go.mod b/vendor/github.com/sirupsen/logrus/go.mod index 94574cc635..8261a2b3a2 100644 --- a/vendor/github.com/sirupsen/logrus/go.mod +++ b/vendor/github.com/sirupsen/logrus/go.mod @@ -6,6 +6,5 @@ require ( github.com/pmezard/go-difflib v1.0.0 // indirect github.com/stretchr/objx v0.1.1 // indirect github.com/stretchr/testify v1.2.2 - golang.org/x/crypto v0.0.0-20180904163835-0709b304e793 golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33 ) diff --git a/vendor/github.com/sirupsen/logrus/go.sum b/vendor/github.com/sirupsen/logrus/go.sum index 133d34ae11..2d787be60d 100644 --- a/vendor/github.com/sirupsen/logrus/go.sum +++ b/vendor/github.com/sirupsen/logrus/go.sum @@ -9,7 +9,5 @@ github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -golang.org/x/crypto v0.0.0-20180904163835-0709b304e793 h1:u+LnwYTOOW7Ukr/fppxEb1Nwz0AtPflrblfvUudpo+I= -golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33 h1:I6FyU15t786LL7oL/hn43zqTuEGr4PN7F4XJ1p4E3Y8= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= diff --git a/vendor/github.com/sirupsen/logrus/json_formatter.go b/vendor/github.com/sirupsen/logrus/json_formatter.go index 2605753599..098a21a067 100644 --- a/vendor/github.com/sirupsen/logrus/json_formatter.go +++ b/vendor/github.com/sirupsen/logrus/json_formatter.go @@ -4,6 +4,7 @@ import ( "bytes" "encoding/json" "fmt" + "runtime" ) type fieldKey string @@ -42,6 +43,12 @@ type JSONFormatter struct { // } FieldMap FieldMap + // CallerPrettyfier can be set by the user to modify the content + // of the function and file keys in the json data when ReportCaller is + // activated. If any of the returned value is the empty string the + // corresponding key will be removed from json fields. + CallerPrettyfier func(*runtime.Frame) (function string, file string) + // PrettyPrint will indent all json logs PrettyPrint bool } @@ -82,8 +89,17 @@ func (f *JSONFormatter) Format(entry *Entry) ([]byte, error) { data[f.FieldMap.resolve(FieldKeyMsg)] = entry.Message data[f.FieldMap.resolve(FieldKeyLevel)] = entry.Level.String() if entry.HasCaller() { - data[f.FieldMap.resolve(FieldKeyFunc)] = entry.Caller.Function - data[f.FieldMap.resolve(FieldKeyFile)] = fmt.Sprintf("%s:%d", entry.Caller.File, entry.Caller.Line) + funcVal := entry.Caller.Function + fileVal := fmt.Sprintf("%s:%d", entry.Caller.File, entry.Caller.Line) + if f.CallerPrettyfier != nil { + funcVal, fileVal = f.CallerPrettyfier(entry.Caller) + } + if funcVal != "" { + data[f.FieldMap.resolve(FieldKeyFunc)] = funcVal + } + if fileVal != "" { + data[f.FieldMap.resolve(FieldKeyFile)] = fileVal + } } var b *bytes.Buffer @@ -98,7 +114,7 @@ func (f *JSONFormatter) Format(entry *Entry) ([]byte, error) { encoder.SetIndent("", " ") } if err := encoder.Encode(data); err != nil { - return nil, fmt.Errorf("Failed to marshal fields to JSON, %v", err) + return nil, fmt.Errorf("failed to marshal fields to JSON, %v", err) } return b.Bytes(), nil diff --git a/vendor/github.com/sirupsen/logrus/logger.go b/vendor/github.com/sirupsen/logrus/logger.go index 9bf64e22ae..c0c0b1e559 100644 --- a/vendor/github.com/sirupsen/logrus/logger.go +++ b/vendor/github.com/sirupsen/logrus/logger.go @@ -1,6 +1,7 @@ package logrus import ( + "context" "io" "os" "sync" @@ -124,6 +125,13 @@ func (logger *Logger) WithError(err error) *Entry { return entry.WithError(err) } +// Add a context to the log entry. +func (logger *Logger) WithContext(ctx context.Context) *Entry { + entry := logger.newEntry() + defer logger.releaseEntry(entry) + return entry.WithContext(ctx) +} + // Overrides the time of the log entry. func (logger *Logger) WithTime(t time.Time) *Entry { entry := logger.newEntry() @@ -200,7 +208,7 @@ func (logger *Logger) Info(args ...interface{}) { func (logger *Logger) Print(args ...interface{}) { entry := logger.newEntry() - entry.Info(args...) + entry.Print(args...) logger.releaseEntry(entry) } @@ -256,7 +264,7 @@ func (logger *Logger) Warnln(args ...interface{}) { } func (logger *Logger) Warningln(args ...interface{}) { - logger.Warn(args...) + logger.Warnln(args...) } func (logger *Logger) Errorln(args ...interface{}) { diff --git a/vendor/github.com/sirupsen/logrus/logrus.go b/vendor/github.com/sirupsen/logrus/logrus.go index c1ca889902..8644761f73 100644 --- a/vendor/github.com/sirupsen/logrus/logrus.go +++ b/vendor/github.com/sirupsen/logrus/logrus.go @@ -74,7 +74,7 @@ func (level Level) MarshalText() ([]byte, error) { return []byte("panic"), nil } - return nil, fmt.Errorf("not a valid lorus level %q", level) + return nil, fmt.Errorf("not a valid logrus level %d", level) } // A constant exposing all logging levels diff --git a/vendor/github.com/sirupsen/logrus/terminal_check_aix.go b/vendor/github.com/sirupsen/logrus/terminal_check_aix.go deleted file mode 100644 index 04fdb7ba37..0000000000 --- a/vendor/github.com/sirupsen/logrus/terminal_check_aix.go +++ /dev/null @@ -1,9 +0,0 @@ -// +build !appengine,!js,!windows,aix - -package logrus - -import "io" - -func checkIfTerminal(w io.Writer) bool { - return false -} diff --git a/vendor/github.com/sirupsen/logrus/terminal_check_bsd.go b/vendor/github.com/sirupsen/logrus/terminal_check_bsd.go new file mode 100644 index 0000000000..3c4f43f91c --- /dev/null +++ b/vendor/github.com/sirupsen/logrus/terminal_check_bsd.go @@ -0,0 +1,13 @@ +// +build darwin dragonfly freebsd netbsd openbsd + +package logrus + +import "golang.org/x/sys/unix" + +const ioctlReadTermios = unix.TIOCGETA + +func isTerminal(fd int) bool { + _, err := unix.IoctlGetTermios(fd, ioctlReadTermios) + return err == nil +} + diff --git a/vendor/github.com/sirupsen/logrus/terminal_check_notappengine.go b/vendor/github.com/sirupsen/logrus/terminal_check_notappengine.go index d46556509e..7be2d87c59 100644 --- a/vendor/github.com/sirupsen/logrus/terminal_check_notappengine.go +++ b/vendor/github.com/sirupsen/logrus/terminal_check_notappengine.go @@ -1,18 +1,16 @@ -// +build !appengine,!js,!windows,!aix +// +build !appengine,!js,!windows package logrus import ( "io" "os" - - "golang.org/x/crypto/ssh/terminal" ) func checkIfTerminal(w io.Writer) bool { switch v := w.(type) { case *os.File: - return terminal.IsTerminal(int(v.Fd())) + return isTerminal(int(v.Fd())) default: return false } diff --git a/vendor/github.com/sirupsen/logrus/terminal_check_unix.go b/vendor/github.com/sirupsen/logrus/terminal_check_unix.go new file mode 100644 index 0000000000..355dc966f0 --- /dev/null +++ b/vendor/github.com/sirupsen/logrus/terminal_check_unix.go @@ -0,0 +1,13 @@ +// +build linux aix + +package logrus + +import "golang.org/x/sys/unix" + +const ioctlReadTermios = unix.TCGETS + +func isTerminal(fd int) bool { + _, err := unix.IoctlGetTermios(fd, ioctlReadTermios) + return err == nil +} + diff --git a/vendor/github.com/sirupsen/logrus/text_formatter.go b/vendor/github.com/sirupsen/logrus/text_formatter.go index fb21649c9a..1569161eb8 100644 --- a/vendor/github.com/sirupsen/logrus/text_formatter.go +++ b/vendor/github.com/sirupsen/logrus/text_formatter.go @@ -12,18 +12,13 @@ import ( ) const ( - nocolor = 0 - red = 31 - green = 32 - yellow = 33 - blue = 36 - gray = 37 + red = 31 + yellow = 33 + blue = 36 + gray = 37 ) -var ( - baseTimestamp time.Time - emptyFieldMap FieldMap -) +var baseTimestamp time.Time func init() { baseTimestamp = time.Now() @@ -77,6 +72,12 @@ type TextFormatter struct { // FieldKeyMsg: "@message"}} FieldMap FieldMap + // CallerPrettyfier can be set by the user to modify the content + // of the function and file keys in the data when ReportCaller is + // activated. If any of the returned value is the empty string the + // corresponding key will be removed from fields. + CallerPrettyfier func(*runtime.Frame) (function string, file string) + terminalInitOnce sync.Once } @@ -118,6 +119,8 @@ func (f *TextFormatter) Format(entry *Entry) ([]byte, error) { keys = append(keys, k) } + var funcVal, fileVal string + fixedKeys := make([]string, 0, 4+len(data)) if !f.DisableTimestamp { fixedKeys = append(fixedKeys, f.FieldMap.resolve(FieldKeyTime)) @@ -130,8 +133,19 @@ func (f *TextFormatter) Format(entry *Entry) ([]byte, error) { fixedKeys = append(fixedKeys, f.FieldMap.resolve(FieldKeyLogrusError)) } if entry.HasCaller() { - fixedKeys = append(fixedKeys, - f.FieldMap.resolve(FieldKeyFunc), f.FieldMap.resolve(FieldKeyFile)) + if f.CallerPrettyfier != nil { + funcVal, fileVal = f.CallerPrettyfier(entry.Caller) + } else { + funcVal = entry.Caller.Function + fileVal = fmt.Sprintf("%s:%d", entry.Caller.File, entry.Caller.Line) + } + + if funcVal != "" { + fixedKeys = append(fixedKeys, f.FieldMap.resolve(FieldKeyFunc)) + } + if fileVal != "" { + fixedKeys = append(fixedKeys, f.FieldMap.resolve(FieldKeyFile)) + } } if !f.DisableSorting { @@ -166,6 +180,7 @@ func (f *TextFormatter) Format(entry *Entry) ([]byte, error) { if f.isColored() { f.printColored(b, entry, keys, data, timestampFormat) } else { + for _, key := range fixedKeys { var value interface{} switch { @@ -178,9 +193,9 @@ func (f *TextFormatter) Format(entry *Entry) ([]byte, error) { case key == f.FieldMap.resolve(FieldKeyLogrusError): value = entry.err case key == f.FieldMap.resolve(FieldKeyFunc) && entry.HasCaller(): - value = entry.Caller.Function + value = funcVal case key == f.FieldMap.resolve(FieldKeyFile) && entry.HasCaller(): - value = fmt.Sprintf("%s:%d", entry.Caller.File, entry.Caller.Line) + value = fileVal default: value = data[key] } @@ -215,10 +230,21 @@ func (f *TextFormatter) printColored(b *bytes.Buffer, entry *Entry, keys []strin entry.Message = strings.TrimSuffix(entry.Message, "\n") caller := "" - if entry.HasCaller() { - caller = fmt.Sprintf("%s:%d %s()", - entry.Caller.File, entry.Caller.Line, entry.Caller.Function) + funcVal := fmt.Sprintf("%s()", entry.Caller.Function) + fileVal := fmt.Sprintf("%s:%d", entry.Caller.File, entry.Caller.Line) + + if f.CallerPrettyfier != nil { + funcVal, fileVal = f.CallerPrettyfier(entry.Caller) + } + + if fileVal == "" { + caller = funcVal + } else if funcVal == "" { + caller = fileVal + } else { + caller = fileVal + " " + funcVal + } } if f.DisableTimestamp { diff --git a/vendor/golang.org/x/crypto/AUTHORS b/vendor/golang.org/x/crypto/AUTHORS deleted file mode 100644 index 2b00ddba0d..0000000000 --- a/vendor/golang.org/x/crypto/AUTHORS +++ /dev/null @@ -1,3 +0,0 @@ -# This source code refers to The Go Authors for copyright purposes. -# The master list of authors is in the main Go distribution, -# visible at https://tip.golang.org/AUTHORS. diff --git a/vendor/golang.org/x/crypto/CONTRIBUTORS b/vendor/golang.org/x/crypto/CONTRIBUTORS deleted file mode 100644 index 1fbd3e976f..0000000000 --- a/vendor/golang.org/x/crypto/CONTRIBUTORS +++ /dev/null @@ -1,3 +0,0 @@ -# This source code was written by the Go contributors. -# The master list of contributors is in the main Go distribution, -# visible at https://tip.golang.org/CONTRIBUTORS. diff --git a/vendor/golang.org/x/crypto/LICENSE b/vendor/golang.org/x/crypto/LICENSE deleted file mode 100644 index 6a66aea5ea..0000000000 --- a/vendor/golang.org/x/crypto/LICENSE +++ /dev/null @@ -1,27 +0,0 @@ -Copyright (c) 2009 The Go Authors. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/golang.org/x/crypto/PATENTS b/vendor/golang.org/x/crypto/PATENTS deleted file mode 100644 index 733099041f..0000000000 --- a/vendor/golang.org/x/crypto/PATENTS +++ /dev/null @@ -1,22 +0,0 @@ -Additional IP Rights Grant (Patents) - -"This implementation" means the copyrightable works distributed by -Google as part of the Go project. - -Google hereby grants to You a perpetual, worldwide, non-exclusive, -no-charge, royalty-free, irrevocable (except as stated in this section) -patent license to make, have made, use, offer to sell, sell, import, -transfer and otherwise run, modify and propagate the contents of this -implementation of Go, where such license applies only to those patent -claims, both currently owned or controlled by Google and acquired in -the future, licensable by Google that are necessarily infringed by this -implementation of Go. This grant does not include claims that would be -infringed only as a consequence of further modification of this -implementation. If you or your agent or exclusive licensee institute or -order or agree to the institution of patent litigation against any -entity (including a cross-claim or counterclaim in a lawsuit) alleging -that this implementation of Go or any code incorporated within this -implementation of Go constitutes direct or contributory patent -infringement, or inducement of patent infringement, then any patent -rights granted to you under this License for this implementation of Go -shall terminate as of the date such litigation is filed. diff --git a/vendor/golang.org/x/crypto/ssh/terminal/terminal.go b/vendor/golang.org/x/crypto/ssh/terminal/terminal.go deleted file mode 100644 index 9d666ffcf0..0000000000 --- a/vendor/golang.org/x/crypto/ssh/terminal/terminal.go +++ /dev/null @@ -1,955 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package terminal - -import ( - "bytes" - "io" - "sync" - "unicode/utf8" -) - -// EscapeCodes contains escape sequences that can be written to the terminal in -// order to achieve different styles of text. -type EscapeCodes struct { - // Foreground colors - Black, Red, Green, Yellow, Blue, Magenta, Cyan, White []byte - - // Reset all attributes - Reset []byte -} - -var vt100EscapeCodes = EscapeCodes{ - Black: []byte{keyEscape, '[', '3', '0', 'm'}, - Red: []byte{keyEscape, '[', '3', '1', 'm'}, - Green: []byte{keyEscape, '[', '3', '2', 'm'}, - Yellow: []byte{keyEscape, '[', '3', '3', 'm'}, - Blue: []byte{keyEscape, '[', '3', '4', 'm'}, - Magenta: []byte{keyEscape, '[', '3', '5', 'm'}, - Cyan: []byte{keyEscape, '[', '3', '6', 'm'}, - White: []byte{keyEscape, '[', '3', '7', 'm'}, - - Reset: []byte{keyEscape, '[', '0', 'm'}, -} - -// Terminal contains the state for running a VT100 terminal that is capable of -// reading lines of input. -type Terminal struct { - // AutoCompleteCallback, if non-null, is called for each keypress with - // the full input line and the current position of the cursor (in - // bytes, as an index into |line|). If it returns ok=false, the key - // press is processed normally. Otherwise it returns a replacement line - // and the new cursor position. - AutoCompleteCallback func(line string, pos int, key rune) (newLine string, newPos int, ok bool) - - // Escape contains a pointer to the escape codes for this terminal. - // It's always a valid pointer, although the escape codes themselves - // may be empty if the terminal doesn't support them. - Escape *EscapeCodes - - // lock protects the terminal and the state in this object from - // concurrent processing of a key press and a Write() call. - lock sync.Mutex - - c io.ReadWriter - prompt []rune - - // line is the current line being entered. - line []rune - // pos is the logical position of the cursor in line - pos int - // echo is true if local echo is enabled - echo bool - // pasteActive is true iff there is a bracketed paste operation in - // progress. - pasteActive bool - - // cursorX contains the current X value of the cursor where the left - // edge is 0. cursorY contains the row number where the first row of - // the current line is 0. - cursorX, cursorY int - // maxLine is the greatest value of cursorY so far. - maxLine int - - termWidth, termHeight int - - // outBuf contains the terminal data to be sent. - outBuf []byte - // remainder contains the remainder of any partial key sequences after - // a read. It aliases into inBuf. - remainder []byte - inBuf [256]byte - - // history contains previously entered commands so that they can be - // accessed with the up and down keys. - history stRingBuffer - // historyIndex stores the currently accessed history entry, where zero - // means the immediately previous entry. - historyIndex int - // When navigating up and down the history it's possible to return to - // the incomplete, initial line. That value is stored in - // historyPending. - historyPending string -} - -// NewTerminal runs a VT100 terminal on the given ReadWriter. If the ReadWriter is -// a local terminal, that terminal must first have been put into raw mode. -// prompt is a string that is written at the start of each input line (i.e. -// "> "). -func NewTerminal(c io.ReadWriter, prompt string) *Terminal { - return &Terminal{ - Escape: &vt100EscapeCodes, - c: c, - prompt: []rune(prompt), - termWidth: 80, - termHeight: 24, - echo: true, - historyIndex: -1, - } -} - -const ( - keyCtrlD = 4 - keyCtrlU = 21 - keyEnter = '\r' - keyEscape = 27 - keyBackspace = 127 - keyUnknown = 0xd800 /* UTF-16 surrogate area */ + iota - keyUp - keyDown - keyLeft - keyRight - keyAltLeft - keyAltRight - keyHome - keyEnd - keyDeleteWord - keyDeleteLine - keyClearScreen - keyPasteStart - keyPasteEnd -) - -var ( - crlf = []byte{'\r', '\n'} - pasteStart = []byte{keyEscape, '[', '2', '0', '0', '~'} - pasteEnd = []byte{keyEscape, '[', '2', '0', '1', '~'} -) - -// bytesToKey tries to parse a key sequence from b. If successful, it returns -// the key and the remainder of the input. Otherwise it returns utf8.RuneError. -func bytesToKey(b []byte, pasteActive bool) (rune, []byte) { - if len(b) == 0 { - return utf8.RuneError, nil - } - - if !pasteActive { - switch b[0] { - case 1: // ^A - return keyHome, b[1:] - case 5: // ^E - return keyEnd, b[1:] - case 8: // ^H - return keyBackspace, b[1:] - case 11: // ^K - return keyDeleteLine, b[1:] - case 12: // ^L - return keyClearScreen, b[1:] - case 23: // ^W - return keyDeleteWord, b[1:] - case 14: // ^N - return keyDown, b[1:] - case 16: // ^P - return keyUp, b[1:] - } - } - - if b[0] != keyEscape { - if !utf8.FullRune(b) { - return utf8.RuneError, b - } - r, l := utf8.DecodeRune(b) - return r, b[l:] - } - - if !pasteActive && len(b) >= 3 && b[0] == keyEscape && b[1] == '[' { - switch b[2] { - case 'A': - return keyUp, b[3:] - case 'B': - return keyDown, b[3:] - case 'C': - return keyRight, b[3:] - case 'D': - return keyLeft, b[3:] - case 'H': - return keyHome, b[3:] - case 'F': - return keyEnd, b[3:] - } - } - - if !pasteActive && len(b) >= 6 && b[0] == keyEscape && b[1] == '[' && b[2] == '1' && b[3] == ';' && b[4] == '3' { - switch b[5] { - case 'C': - return keyAltRight, b[6:] - case 'D': - return keyAltLeft, b[6:] - } - } - - if !pasteActive && len(b) >= 6 && bytes.Equal(b[:6], pasteStart) { - return keyPasteStart, b[6:] - } - - if pasteActive && len(b) >= 6 && bytes.Equal(b[:6], pasteEnd) { - return keyPasteEnd, b[6:] - } - - // If we get here then we have a key that we don't recognise, or a - // partial sequence. It's not clear how one should find the end of a - // sequence without knowing them all, but it seems that [a-zA-Z~] only - // appears at the end of a sequence. - for i, c := range b[0:] { - if c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c == '~' { - return keyUnknown, b[i+1:] - } - } - - return utf8.RuneError, b -} - -// queue appends data to the end of t.outBuf -func (t *Terminal) queue(data []rune) { - t.outBuf = append(t.outBuf, []byte(string(data))...) -} - -var eraseUnderCursor = []rune{' ', keyEscape, '[', 'D'} -var space = []rune{' '} - -func isPrintable(key rune) bool { - isInSurrogateArea := key >= 0xd800 && key <= 0xdbff - return key >= 32 && !isInSurrogateArea -} - -// moveCursorToPos appends data to t.outBuf which will move the cursor to the -// given, logical position in the text. -func (t *Terminal) moveCursorToPos(pos int) { - if !t.echo { - return - } - - x := visualLength(t.prompt) + pos - y := x / t.termWidth - x = x % t.termWidth - - up := 0 - if y < t.cursorY { - up = t.cursorY - y - } - - down := 0 - if y > t.cursorY { - down = y - t.cursorY - } - - left := 0 - if x < t.cursorX { - left = t.cursorX - x - } - - right := 0 - if x > t.cursorX { - right = x - t.cursorX - } - - t.cursorX = x - t.cursorY = y - t.move(up, down, left, right) -} - -func (t *Terminal) move(up, down, left, right int) { - movement := make([]rune, 3*(up+down+left+right)) - m := movement - for i := 0; i < up; i++ { - m[0] = keyEscape - m[1] = '[' - m[2] = 'A' - m = m[3:] - } - for i := 0; i < down; i++ { - m[0] = keyEscape - m[1] = '[' - m[2] = 'B' - m = m[3:] - } - for i := 0; i < left; i++ { - m[0] = keyEscape - m[1] = '[' - m[2] = 'D' - m = m[3:] - } - for i := 0; i < right; i++ { - m[0] = keyEscape - m[1] = '[' - m[2] = 'C' - m = m[3:] - } - - t.queue(movement) -} - -func (t *Terminal) clearLineToRight() { - op := []rune{keyEscape, '[', 'K'} - t.queue(op) -} - -const maxLineLength = 4096 - -func (t *Terminal) setLine(newLine []rune, newPos int) { - if t.echo { - t.moveCursorToPos(0) - t.writeLine(newLine) - for i := len(newLine); i < len(t.line); i++ { - t.writeLine(space) - } - t.moveCursorToPos(newPos) - } - t.line = newLine - t.pos = newPos -} - -func (t *Terminal) advanceCursor(places int) { - t.cursorX += places - t.cursorY += t.cursorX / t.termWidth - if t.cursorY > t.maxLine { - t.maxLine = t.cursorY - } - t.cursorX = t.cursorX % t.termWidth - - if places > 0 && t.cursorX == 0 { - // Normally terminals will advance the current position - // when writing a character. But that doesn't happen - // for the last character in a line. However, when - // writing a character (except a new line) that causes - // a line wrap, the position will be advanced two - // places. - // - // So, if we are stopping at the end of a line, we - // need to write a newline so that our cursor can be - // advanced to the next line. - t.outBuf = append(t.outBuf, '\r', '\n') - } -} - -func (t *Terminal) eraseNPreviousChars(n int) { - if n == 0 { - return - } - - if t.pos < n { - n = t.pos - } - t.pos -= n - t.moveCursorToPos(t.pos) - - copy(t.line[t.pos:], t.line[n+t.pos:]) - t.line = t.line[:len(t.line)-n] - if t.echo { - t.writeLine(t.line[t.pos:]) - for i := 0; i < n; i++ { - t.queue(space) - } - t.advanceCursor(n) - t.moveCursorToPos(t.pos) - } -} - -// countToLeftWord returns then number of characters from the cursor to the -// start of the previous word. -func (t *Terminal) countToLeftWord() int { - if t.pos == 0 { - return 0 - } - - pos := t.pos - 1 - for pos > 0 { - if t.line[pos] != ' ' { - break - } - pos-- - } - for pos > 0 { - if t.line[pos] == ' ' { - pos++ - break - } - pos-- - } - - return t.pos - pos -} - -// countToRightWord returns then number of characters from the cursor to the -// start of the next word. -func (t *Terminal) countToRightWord() int { - pos := t.pos - for pos < len(t.line) { - if t.line[pos] == ' ' { - break - } - pos++ - } - for pos < len(t.line) { - if t.line[pos] != ' ' { - break - } - pos++ - } - return pos - t.pos -} - -// visualLength returns the number of visible glyphs in s. -func visualLength(runes []rune) int { - inEscapeSeq := false - length := 0 - - for _, r := range runes { - switch { - case inEscapeSeq: - if (r >= 'a' && r <= 'z') || (r >= 'A' && r <= 'Z') { - inEscapeSeq = false - } - case r == '\x1b': - inEscapeSeq = true - default: - length++ - } - } - - return length -} - -// handleKey processes the given key and, optionally, returns a line of text -// that the user has entered. -func (t *Terminal) handleKey(key rune) (line string, ok bool) { - if t.pasteActive && key != keyEnter { - t.addKeyToLine(key) - return - } - - switch key { - case keyBackspace: - if t.pos == 0 { - return - } - t.eraseNPreviousChars(1) - case keyAltLeft: - // move left by a word. - t.pos -= t.countToLeftWord() - t.moveCursorToPos(t.pos) - case keyAltRight: - // move right by a word. - t.pos += t.countToRightWord() - t.moveCursorToPos(t.pos) - case keyLeft: - if t.pos == 0 { - return - } - t.pos-- - t.moveCursorToPos(t.pos) - case keyRight: - if t.pos == len(t.line) { - return - } - t.pos++ - t.moveCursorToPos(t.pos) - case keyHome: - if t.pos == 0 { - return - } - t.pos = 0 - t.moveCursorToPos(t.pos) - case keyEnd: - if t.pos == len(t.line) { - return - } - t.pos = len(t.line) - t.moveCursorToPos(t.pos) - case keyUp: - entry, ok := t.history.NthPreviousEntry(t.historyIndex + 1) - if !ok { - return "", false - } - if t.historyIndex == -1 { - t.historyPending = string(t.line) - } - t.historyIndex++ - runes := []rune(entry) - t.setLine(runes, len(runes)) - case keyDown: - switch t.historyIndex { - case -1: - return - case 0: - runes := []rune(t.historyPending) - t.setLine(runes, len(runes)) - t.historyIndex-- - default: - entry, ok := t.history.NthPreviousEntry(t.historyIndex - 1) - if ok { - t.historyIndex-- - runes := []rune(entry) - t.setLine(runes, len(runes)) - } - } - case keyEnter: - t.moveCursorToPos(len(t.line)) - t.queue([]rune("\r\n")) - line = string(t.line) - ok = true - t.line = t.line[:0] - t.pos = 0 - t.cursorX = 0 - t.cursorY = 0 - t.maxLine = 0 - case keyDeleteWord: - // Delete zero or more spaces and then one or more characters. - t.eraseNPreviousChars(t.countToLeftWord()) - case keyDeleteLine: - // Delete everything from the current cursor position to the - // end of line. - for i := t.pos; i < len(t.line); i++ { - t.queue(space) - t.advanceCursor(1) - } - t.line = t.line[:t.pos] - t.moveCursorToPos(t.pos) - case keyCtrlD: - // Erase the character under the current position. - // The EOF case when the line is empty is handled in - // readLine(). - if t.pos < len(t.line) { - t.pos++ - t.eraseNPreviousChars(1) - } - case keyCtrlU: - t.eraseNPreviousChars(t.pos) - case keyClearScreen: - // Erases the screen and moves the cursor to the home position. - t.queue([]rune("\x1b[2J\x1b[H")) - t.queue(t.prompt) - t.cursorX, t.cursorY = 0, 0 - t.advanceCursor(visualLength(t.prompt)) - t.setLine(t.line, t.pos) - default: - if t.AutoCompleteCallback != nil { - prefix := string(t.line[:t.pos]) - suffix := string(t.line[t.pos:]) - - t.lock.Unlock() - newLine, newPos, completeOk := t.AutoCompleteCallback(prefix+suffix, len(prefix), key) - t.lock.Lock() - - if completeOk { - t.setLine([]rune(newLine), utf8.RuneCount([]byte(newLine)[:newPos])) - return - } - } - if !isPrintable(key) { - return - } - if len(t.line) == maxLineLength { - return - } - t.addKeyToLine(key) - } - return -} - -// addKeyToLine inserts the given key at the current position in the current -// line. -func (t *Terminal) addKeyToLine(key rune) { - if len(t.line) == cap(t.line) { - newLine := make([]rune, len(t.line), 2*(1+len(t.line))) - copy(newLine, t.line) - t.line = newLine - } - t.line = t.line[:len(t.line)+1] - copy(t.line[t.pos+1:], t.line[t.pos:]) - t.line[t.pos] = key - if t.echo { - t.writeLine(t.line[t.pos:]) - } - t.pos++ - t.moveCursorToPos(t.pos) -} - -func (t *Terminal) writeLine(line []rune) { - for len(line) != 0 { - remainingOnLine := t.termWidth - t.cursorX - todo := len(line) - if todo > remainingOnLine { - todo = remainingOnLine - } - t.queue(line[:todo]) - t.advanceCursor(visualLength(line[:todo])) - line = line[todo:] - } -} - -// writeWithCRLF writes buf to w but replaces all occurrences of \n with \r\n. -func writeWithCRLF(w io.Writer, buf []byte) (n int, err error) { - for len(buf) > 0 { - i := bytes.IndexByte(buf, '\n') - todo := len(buf) - if i >= 0 { - todo = i - } - - var nn int - nn, err = w.Write(buf[:todo]) - n += nn - if err != nil { - return n, err - } - buf = buf[todo:] - - if i >= 0 { - if _, err = w.Write(crlf); err != nil { - return n, err - } - n++ - buf = buf[1:] - } - } - - return n, nil -} - -func (t *Terminal) Write(buf []byte) (n int, err error) { - t.lock.Lock() - defer t.lock.Unlock() - - if t.cursorX == 0 && t.cursorY == 0 { - // This is the easy case: there's nothing on the screen that we - // have to move out of the way. - return writeWithCRLF(t.c, buf) - } - - // We have a prompt and possibly user input on the screen. We - // have to clear it first. - t.move(0 /* up */, 0 /* down */, t.cursorX /* left */, 0 /* right */) - t.cursorX = 0 - t.clearLineToRight() - - for t.cursorY > 0 { - t.move(1 /* up */, 0, 0, 0) - t.cursorY-- - t.clearLineToRight() - } - - if _, err = t.c.Write(t.outBuf); err != nil { - return - } - t.outBuf = t.outBuf[:0] - - if n, err = writeWithCRLF(t.c, buf); err != nil { - return - } - - t.writeLine(t.prompt) - if t.echo { - t.writeLine(t.line) - } - - t.moveCursorToPos(t.pos) - - if _, err = t.c.Write(t.outBuf); err != nil { - return - } - t.outBuf = t.outBuf[:0] - return -} - -// ReadPassword temporarily changes the prompt and reads a password, without -// echo, from the terminal. -func (t *Terminal) ReadPassword(prompt string) (line string, err error) { - t.lock.Lock() - defer t.lock.Unlock() - - oldPrompt := t.prompt - t.prompt = []rune(prompt) - t.echo = false - - line, err = t.readLine() - - t.prompt = oldPrompt - t.echo = true - - return -} - -// ReadLine returns a line of input from the terminal. -func (t *Terminal) ReadLine() (line string, err error) { - t.lock.Lock() - defer t.lock.Unlock() - - return t.readLine() -} - -func (t *Terminal) readLine() (line string, err error) { - // t.lock must be held at this point - - if t.cursorX == 0 && t.cursorY == 0 { - t.writeLine(t.prompt) - t.c.Write(t.outBuf) - t.outBuf = t.outBuf[:0] - } - - lineIsPasted := t.pasteActive - - for { - rest := t.remainder - lineOk := false - for !lineOk { - var key rune - key, rest = bytesToKey(rest, t.pasteActive) - if key == utf8.RuneError { - break - } - if !t.pasteActive { - if key == keyCtrlD { - if len(t.line) == 0 { - return "", io.EOF - } - } - if key == keyPasteStart { - t.pasteActive = true - if len(t.line) == 0 { - lineIsPasted = true - } - continue - } - } else if key == keyPasteEnd { - t.pasteActive = false - continue - } - if !t.pasteActive { - lineIsPasted = false - } - line, lineOk = t.handleKey(key) - } - if len(rest) > 0 { - n := copy(t.inBuf[:], rest) - t.remainder = t.inBuf[:n] - } else { - t.remainder = nil - } - t.c.Write(t.outBuf) - t.outBuf = t.outBuf[:0] - if lineOk { - if t.echo { - t.historyIndex = -1 - t.history.Add(line) - } - if lineIsPasted { - err = ErrPasteIndicator - } - return - } - - // t.remainder is a slice at the beginning of t.inBuf - // containing a partial key sequence - readBuf := t.inBuf[len(t.remainder):] - var n int - - t.lock.Unlock() - n, err = t.c.Read(readBuf) - t.lock.Lock() - - if err != nil { - return - } - - t.remainder = t.inBuf[:n+len(t.remainder)] - } -} - -// SetPrompt sets the prompt to be used when reading subsequent lines. -func (t *Terminal) SetPrompt(prompt string) { - t.lock.Lock() - defer t.lock.Unlock() - - t.prompt = []rune(prompt) -} - -func (t *Terminal) clearAndRepaintLinePlusNPrevious(numPrevLines int) { - // Move cursor to column zero at the start of the line. - t.move(t.cursorY, 0, t.cursorX, 0) - t.cursorX, t.cursorY = 0, 0 - t.clearLineToRight() - for t.cursorY < numPrevLines { - // Move down a line - t.move(0, 1, 0, 0) - t.cursorY++ - t.clearLineToRight() - } - // Move back to beginning. - t.move(t.cursorY, 0, 0, 0) - t.cursorX, t.cursorY = 0, 0 - - t.queue(t.prompt) - t.advanceCursor(visualLength(t.prompt)) - t.writeLine(t.line) - t.moveCursorToPos(t.pos) -} - -func (t *Terminal) SetSize(width, height int) error { - t.lock.Lock() - defer t.lock.Unlock() - - if width == 0 { - width = 1 - } - - oldWidth := t.termWidth - t.termWidth, t.termHeight = width, height - - switch { - case width == oldWidth: - // If the width didn't change then nothing else needs to be - // done. - return nil - case len(t.line) == 0 && t.cursorX == 0 && t.cursorY == 0: - // If there is nothing on current line and no prompt printed, - // just do nothing - return nil - case width < oldWidth: - // Some terminals (e.g. xterm) will truncate lines that were - // too long when shinking. Others, (e.g. gnome-terminal) will - // attempt to wrap them. For the former, repainting t.maxLine - // works great, but that behaviour goes badly wrong in the case - // of the latter because they have doubled every full line. - - // We assume that we are working on a terminal that wraps lines - // and adjust the cursor position based on every previous line - // wrapping and turning into two. This causes the prompt on - // xterms to move upwards, which isn't great, but it avoids a - // huge mess with gnome-terminal. - if t.cursorX >= t.termWidth { - t.cursorX = t.termWidth - 1 - } - t.cursorY *= 2 - t.clearAndRepaintLinePlusNPrevious(t.maxLine * 2) - case width > oldWidth: - // If the terminal expands then our position calculations will - // be wrong in the future because we think the cursor is - // |t.pos| chars into the string, but there will be a gap at - // the end of any wrapped line. - // - // But the position will actually be correct until we move, so - // we can move back to the beginning and repaint everything. - t.clearAndRepaintLinePlusNPrevious(t.maxLine) - } - - _, err := t.c.Write(t.outBuf) - t.outBuf = t.outBuf[:0] - return err -} - -type pasteIndicatorError struct{} - -func (pasteIndicatorError) Error() string { - return "terminal: ErrPasteIndicator not correctly handled" -} - -// ErrPasteIndicator may be returned from ReadLine as the error, in addition -// to valid line data. It indicates that bracketed paste mode is enabled and -// that the returned line consists only of pasted data. Programs may wish to -// interpret pasted data more literally than typed data. -var ErrPasteIndicator = pasteIndicatorError{} - -// SetBracketedPasteMode requests that the terminal bracket paste operations -// with markers. Not all terminals support this but, if it is supported, then -// enabling this mode will stop any autocomplete callback from running due to -// pastes. Additionally, any lines that are completely pasted will be returned -// from ReadLine with the error set to ErrPasteIndicator. -func (t *Terminal) SetBracketedPasteMode(on bool) { - if on { - io.WriteString(t.c, "\x1b[?2004h") - } else { - io.WriteString(t.c, "\x1b[?2004l") - } -} - -// stRingBuffer is a ring buffer of strings. -type stRingBuffer struct { - // entries contains max elements. - entries []string - max int - // head contains the index of the element most recently added to the ring. - head int - // size contains the number of elements in the ring. - size int -} - -func (s *stRingBuffer) Add(a string) { - if s.entries == nil { - const defaultNumEntries = 100 - s.entries = make([]string, defaultNumEntries) - s.max = defaultNumEntries - } - - s.head = (s.head + 1) % s.max - s.entries[s.head] = a - if s.size < s.max { - s.size++ - } -} - -// NthPreviousEntry returns the value passed to the nth previous call to Add. -// If n is zero then the immediately prior value is returned, if one, then the -// next most recent, and so on. If such an element doesn't exist then ok is -// false. -func (s *stRingBuffer) NthPreviousEntry(n int) (value string, ok bool) { - if n >= s.size { - return "", false - } - index := s.head - n - if index < 0 { - index += s.max - } - return s.entries[index], true -} - -// readPasswordLine reads from reader until it finds \n or io.EOF. -// The slice returned does not include the \n. -// readPasswordLine also ignores any \r it finds. -func readPasswordLine(reader io.Reader) ([]byte, error) { - var buf [1]byte - var ret []byte - - for { - n, err := reader.Read(buf[:]) - if n > 0 { - switch buf[0] { - case '\n': - return ret, nil - case '\r': - // remove \r from passwords on Windows - default: - ret = append(ret, buf[0]) - } - continue - } - if err != nil { - if err == io.EOF && len(ret) > 0 { - return ret, nil - } - return ret, err - } - } -} diff --git a/vendor/golang.org/x/crypto/ssh/terminal/util.go b/vendor/golang.org/x/crypto/ssh/terminal/util.go deleted file mode 100644 index 3911040840..0000000000 --- a/vendor/golang.org/x/crypto/ssh/terminal/util.go +++ /dev/null @@ -1,114 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build aix darwin dragonfly freebsd linux,!appengine netbsd openbsd - -// Package terminal provides support functions for dealing with terminals, as -// commonly found on UNIX systems. -// -// Putting a terminal into raw mode is the most common requirement: -// -// oldState, err := terminal.MakeRaw(0) -// if err != nil { -// panic(err) -// } -// defer terminal.Restore(0, oldState) -package terminal // import "golang.org/x/crypto/ssh/terminal" - -import ( - "golang.org/x/sys/unix" -) - -// State contains the state of a terminal. -type State struct { - termios unix.Termios -} - -// IsTerminal returns whether the given file descriptor is a terminal. -func IsTerminal(fd int) bool { - _, err := unix.IoctlGetTermios(fd, ioctlReadTermios) - return err == nil -} - -// MakeRaw put the terminal connected to the given file descriptor into raw -// mode and returns the previous state of the terminal so that it can be -// restored. -func MakeRaw(fd int) (*State, error) { - termios, err := unix.IoctlGetTermios(fd, ioctlReadTermios) - if err != nil { - return nil, err - } - - oldState := State{termios: *termios} - - // This attempts to replicate the behaviour documented for cfmakeraw in - // the termios(3) manpage. - termios.Iflag &^= unix.IGNBRK | unix.BRKINT | unix.PARMRK | unix.ISTRIP | unix.INLCR | unix.IGNCR | unix.ICRNL | unix.IXON - termios.Oflag &^= unix.OPOST - termios.Lflag &^= unix.ECHO | unix.ECHONL | unix.ICANON | unix.ISIG | unix.IEXTEN - termios.Cflag &^= unix.CSIZE | unix.PARENB - termios.Cflag |= unix.CS8 - termios.Cc[unix.VMIN] = 1 - termios.Cc[unix.VTIME] = 0 - if err := unix.IoctlSetTermios(fd, ioctlWriteTermios, termios); err != nil { - return nil, err - } - - return &oldState, nil -} - -// GetState returns the current state of a terminal which may be useful to -// restore the terminal after a signal. -func GetState(fd int) (*State, error) { - termios, err := unix.IoctlGetTermios(fd, ioctlReadTermios) - if err != nil { - return nil, err - } - - return &State{termios: *termios}, nil -} - -// Restore restores the terminal connected to the given file descriptor to a -// previous state. -func Restore(fd int, state *State) error { - return unix.IoctlSetTermios(fd, ioctlWriteTermios, &state.termios) -} - -// GetSize returns the dimensions of the given terminal. -func GetSize(fd int) (width, height int, err error) { - ws, err := unix.IoctlGetWinsize(fd, unix.TIOCGWINSZ) - if err != nil { - return -1, -1, err - } - return int(ws.Col), int(ws.Row), nil -} - -// passwordReader is an io.Reader that reads from a specific file descriptor. -type passwordReader int - -func (r passwordReader) Read(buf []byte) (int, error) { - return unix.Read(int(r), buf) -} - -// ReadPassword reads a line of input from a terminal without local echo. This -// is commonly used for inputting passwords and other sensitive data. The slice -// returned does not include the \n. -func ReadPassword(fd int) ([]byte, error) { - termios, err := unix.IoctlGetTermios(fd, ioctlReadTermios) - if err != nil { - return nil, err - } - - newState := *termios - newState.Lflag &^= unix.ECHO - newState.Lflag |= unix.ICANON | unix.ISIG - newState.Iflag |= unix.ICRNL - if err := unix.IoctlSetTermios(fd, ioctlWriteTermios, &newState); err != nil { - return nil, err - } - - defer unix.IoctlSetTermios(fd, ioctlWriteTermios, termios) - - return readPasswordLine(passwordReader(fd)) -} diff --git a/vendor/golang.org/x/crypto/ssh/terminal/util_aix.go b/vendor/golang.org/x/crypto/ssh/terminal/util_aix.go deleted file mode 100644 index dfcd627859..0000000000 --- a/vendor/golang.org/x/crypto/ssh/terminal/util_aix.go +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright 2018 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build aix - -package terminal - -import "golang.org/x/sys/unix" - -const ioctlReadTermios = unix.TCGETS -const ioctlWriteTermios = unix.TCSETS diff --git a/vendor/golang.org/x/crypto/ssh/terminal/util_bsd.go b/vendor/golang.org/x/crypto/ssh/terminal/util_bsd.go deleted file mode 100644 index cb23a59049..0000000000 --- a/vendor/golang.org/x/crypto/ssh/terminal/util_bsd.go +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright 2013 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build darwin dragonfly freebsd netbsd openbsd - -package terminal - -import "golang.org/x/sys/unix" - -const ioctlReadTermios = unix.TIOCGETA -const ioctlWriteTermios = unix.TIOCSETA diff --git a/vendor/golang.org/x/crypto/ssh/terminal/util_linux.go b/vendor/golang.org/x/crypto/ssh/terminal/util_linux.go deleted file mode 100644 index 5fadfe8a1d..0000000000 --- a/vendor/golang.org/x/crypto/ssh/terminal/util_linux.go +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright 2013 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package terminal - -import "golang.org/x/sys/unix" - -const ioctlReadTermios = unix.TCGETS -const ioctlWriteTermios = unix.TCSETS diff --git a/vendor/golang.org/x/crypto/ssh/terminal/util_plan9.go b/vendor/golang.org/x/crypto/ssh/terminal/util_plan9.go deleted file mode 100644 index 9317ac7ede..0000000000 --- a/vendor/golang.org/x/crypto/ssh/terminal/util_plan9.go +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright 2016 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package terminal provides support functions for dealing with terminals, as -// commonly found on UNIX systems. -// -// Putting a terminal into raw mode is the most common requirement: -// -// oldState, err := terminal.MakeRaw(0) -// if err != nil { -// panic(err) -// } -// defer terminal.Restore(0, oldState) -package terminal - -import ( - "fmt" - "runtime" -) - -type State struct{} - -// IsTerminal returns whether the given file descriptor is a terminal. -func IsTerminal(fd int) bool { - return false -} - -// MakeRaw put the terminal connected to the given file descriptor into raw -// mode and returns the previous state of the terminal so that it can be -// restored. -func MakeRaw(fd int) (*State, error) { - return nil, fmt.Errorf("terminal: MakeRaw not implemented on %s/%s", runtime.GOOS, runtime.GOARCH) -} - -// GetState returns the current state of a terminal which may be useful to -// restore the terminal after a signal. -func GetState(fd int) (*State, error) { - return nil, fmt.Errorf("terminal: GetState not implemented on %s/%s", runtime.GOOS, runtime.GOARCH) -} - -// Restore restores the terminal connected to the given file descriptor to a -// previous state. -func Restore(fd int, state *State) error { - return fmt.Errorf("terminal: Restore not implemented on %s/%s", runtime.GOOS, runtime.GOARCH) -} - -// GetSize returns the dimensions of the given terminal. -func GetSize(fd int) (width, height int, err error) { - return 0, 0, fmt.Errorf("terminal: GetSize not implemented on %s/%s", runtime.GOOS, runtime.GOARCH) -} - -// ReadPassword reads a line of input from a terminal without local echo. This -// is commonly used for inputting passwords and other sensitive data. The slice -// returned does not include the \n. -func ReadPassword(fd int) ([]byte, error) { - return nil, fmt.Errorf("terminal: ReadPassword not implemented on %s/%s", runtime.GOOS, runtime.GOARCH) -} diff --git a/vendor/golang.org/x/crypto/ssh/terminal/util_solaris.go b/vendor/golang.org/x/crypto/ssh/terminal/util_solaris.go deleted file mode 100644 index 3d5f06a9f0..0000000000 --- a/vendor/golang.org/x/crypto/ssh/terminal/util_solaris.go +++ /dev/null @@ -1,124 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build solaris - -package terminal // import "golang.org/x/crypto/ssh/terminal" - -import ( - "golang.org/x/sys/unix" - "io" - "syscall" -) - -// State contains the state of a terminal. -type State struct { - termios unix.Termios -} - -// IsTerminal returns whether the given file descriptor is a terminal. -func IsTerminal(fd int) bool { - _, err := unix.IoctlGetTermio(fd, unix.TCGETA) - return err == nil -} - -// ReadPassword reads a line of input from a terminal without local echo. This -// is commonly used for inputting passwords and other sensitive data. The slice -// returned does not include the \n. -func ReadPassword(fd int) ([]byte, error) { - // see also: http://src.illumos.org/source/xref/illumos-gate/usr/src/lib/libast/common/uwin/getpass.c - val, err := unix.IoctlGetTermios(fd, unix.TCGETS) - if err != nil { - return nil, err - } - oldState := *val - - newState := oldState - newState.Lflag &^= syscall.ECHO - newState.Lflag |= syscall.ICANON | syscall.ISIG - newState.Iflag |= syscall.ICRNL - err = unix.IoctlSetTermios(fd, unix.TCSETS, &newState) - if err != nil { - return nil, err - } - - defer unix.IoctlSetTermios(fd, unix.TCSETS, &oldState) - - var buf [16]byte - var ret []byte - for { - n, err := syscall.Read(fd, buf[:]) - if err != nil { - return nil, err - } - if n == 0 { - if len(ret) == 0 { - return nil, io.EOF - } - break - } - if buf[n-1] == '\n' { - n-- - } - ret = append(ret, buf[:n]...) - if n < len(buf) { - break - } - } - - return ret, nil -} - -// MakeRaw puts the terminal connected to the given file descriptor into raw -// mode and returns the previous state of the terminal so that it can be -// restored. -// see http://cr.illumos.org/~webrev/andy_js/1060/ -func MakeRaw(fd int) (*State, error) { - termios, err := unix.IoctlGetTermios(fd, unix.TCGETS) - if err != nil { - return nil, err - } - - oldState := State{termios: *termios} - - termios.Iflag &^= unix.IGNBRK | unix.BRKINT | unix.PARMRK | unix.ISTRIP | unix.INLCR | unix.IGNCR | unix.ICRNL | unix.IXON - termios.Oflag &^= unix.OPOST - termios.Lflag &^= unix.ECHO | unix.ECHONL | unix.ICANON | unix.ISIG | unix.IEXTEN - termios.Cflag &^= unix.CSIZE | unix.PARENB - termios.Cflag |= unix.CS8 - termios.Cc[unix.VMIN] = 1 - termios.Cc[unix.VTIME] = 0 - - if err := unix.IoctlSetTermios(fd, unix.TCSETS, termios); err != nil { - return nil, err - } - - return &oldState, nil -} - -// Restore restores the terminal connected to the given file descriptor to a -// previous state. -func Restore(fd int, oldState *State) error { - return unix.IoctlSetTermios(fd, unix.TCSETS, &oldState.termios) -} - -// GetState returns the current state of a terminal which may be useful to -// restore the terminal after a signal. -func GetState(fd int) (*State, error) { - termios, err := unix.IoctlGetTermios(fd, unix.TCGETS) - if err != nil { - return nil, err - } - - return &State{termios: *termios}, nil -} - -// GetSize returns the dimensions of the given terminal. -func GetSize(fd int) (width, height int, err error) { - ws, err := unix.IoctlGetWinsize(fd, unix.TIOCGWINSZ) - if err != nil { - return 0, 0, err - } - return int(ws.Col), int(ws.Row), nil -} diff --git a/vendor/golang.org/x/crypto/ssh/terminal/util_windows.go b/vendor/golang.org/x/crypto/ssh/terminal/util_windows.go deleted file mode 100644 index 5cfdf8f3f0..0000000000 --- a/vendor/golang.org/x/crypto/ssh/terminal/util_windows.go +++ /dev/null @@ -1,105 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build windows - -// Package terminal provides support functions for dealing with terminals, as -// commonly found on UNIX systems. -// -// Putting a terminal into raw mode is the most common requirement: -// -// oldState, err := terminal.MakeRaw(0) -// if err != nil { -// panic(err) -// } -// defer terminal.Restore(0, oldState) -package terminal - -import ( - "os" - - "golang.org/x/sys/windows" -) - -type State struct { - mode uint32 -} - -// IsTerminal returns whether the given file descriptor is a terminal. -func IsTerminal(fd int) bool { - var st uint32 - err := windows.GetConsoleMode(windows.Handle(fd), &st) - return err == nil -} - -// MakeRaw put the terminal connected to the given file descriptor into raw -// mode and returns the previous state of the terminal so that it can be -// restored. -func MakeRaw(fd int) (*State, error) { - var st uint32 - if err := windows.GetConsoleMode(windows.Handle(fd), &st); err != nil { - return nil, err - } - raw := st &^ (windows.ENABLE_ECHO_INPUT | windows.ENABLE_PROCESSED_INPUT | windows.ENABLE_LINE_INPUT | windows.ENABLE_PROCESSED_OUTPUT) - if err := windows.SetConsoleMode(windows.Handle(fd), raw); err != nil { - return nil, err - } - return &State{st}, nil -} - -// GetState returns the current state of a terminal which may be useful to -// restore the terminal after a signal. -func GetState(fd int) (*State, error) { - var st uint32 - if err := windows.GetConsoleMode(windows.Handle(fd), &st); err != nil { - return nil, err - } - return &State{st}, nil -} - -// Restore restores the terminal connected to the given file descriptor to a -// previous state. -func Restore(fd int, state *State) error { - return windows.SetConsoleMode(windows.Handle(fd), state.mode) -} - -// GetSize returns the visible dimensions of the given terminal. -// -// These dimensions don't include any scrollback buffer height. -func GetSize(fd int) (width, height int, err error) { - var info windows.ConsoleScreenBufferInfo - if err := windows.GetConsoleScreenBufferInfo(windows.Handle(fd), &info); err != nil { - return 0, 0, err - } - return int(info.Window.Right - info.Window.Left + 1), int(info.Window.Bottom - info.Window.Top + 1), nil -} - -// ReadPassword reads a line of input from a terminal without local echo. This -// is commonly used for inputting passwords and other sensitive data. The slice -// returned does not include the \n. -func ReadPassword(fd int) ([]byte, error) { - var st uint32 - if err := windows.GetConsoleMode(windows.Handle(fd), &st); err != nil { - return nil, err - } - old := st - - st &^= (windows.ENABLE_ECHO_INPUT) - st |= (windows.ENABLE_PROCESSED_INPUT | windows.ENABLE_LINE_INPUT | windows.ENABLE_PROCESSED_OUTPUT) - if err := windows.SetConsoleMode(windows.Handle(fd), st); err != nil { - return nil, err - } - - defer windows.SetConsoleMode(windows.Handle(fd), old) - - var h windows.Handle - p, _ := windows.GetCurrentProcess() - if err := windows.DuplicateHandle(p, windows.Handle(fd), p, &h, 0, false, windows.DUPLICATE_SAME_ACCESS); err != nil { - return nil, err - } - - f := os.NewFile(uintptr(h), "stdin") - defer f.Close() - return readPasswordLine(f) -} diff --git a/vendor/modules.txt b/vendor/modules.txt index a4a6b97fbd..6525c566e2 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -122,7 +122,7 @@ github.com/prometheus/procfs github.com/prometheus/procfs/nfs github.com/prometheus/procfs/xfs github.com/prometheus/procfs/internal/util -# github.com/sirupsen/logrus v1.3.0 +# github.com/sirupsen/logrus v1.4.1 github.com/sirupsen/logrus github.com/sirupsen/logrus/hooks/syslog # github.com/ugorji/go/codec v0.0.0-20181022190402-e5e69e061d4f @@ -146,8 +146,6 @@ go.opencensus.io/trace/internal go.opencensus.io/trace/tracestate go.opencensus.io/exporter/jaeger/internal/gen-go/jaeger go.opencensus.io -# golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 -golang.org/x/crypto/ssh/terminal # golang.org/x/net v0.0.0-20181217023233-e147a9138326 golang.org/x/net/trace golang.org/x/net/context From bff37484206281dff14e6d0f7430ba700c1b851e Mon Sep 17 00:00:00 2001 From: Reed Allman Date: Thu, 18 Apr 2019 03:51:58 -0700 Subject: [PATCH 5/9] reasonable compromise with config --- api/agent/agent.go | 4 ++-- api/agent/call.go | 31 +++++++++++++++---------------- api/agent/func_logger.go | 8 ++++---- api/agent/lb_agent.go | 2 +- api/server/runner_fninvoke.go | 3 --- 5 files changed, 22 insertions(+), 26 deletions(-) diff --git a/api/agent/agent.go b/api/agent/agent.go index b00176f6cb..71e2297436 100644 --- a/api/agent/agent.go +++ b/api/agent/agent.go @@ -1206,10 +1206,10 @@ func newHotContainer(ctx context.Context, evictor Evictor, call *call, cfg *Conf // fix is to make a new one each swap, it's cheap enough to be doable. // TODO(reed): we should only do this if they configure to log stderr, not if they use WithLogger(), // for now use explicit disable with DisableDebugUserLogs - sec := &nopCloser{newLogWriter( + sec := newLogWriter( logrus.WithFields(logrus.Fields{"tag": "stderr", "app_id": call.AppID, "fn_id": call.FnID, "image": call.Image, "container_id": id}), cfg.UserLogLevel, - )} + ) gw.Swap(newLineWriterWithBuffer(buf1, sec)) stderr = gw bufs = append(bufs, buf1) diff --git a/api/agent/call.go b/api/agent/call.go index a50186cc78..5652ed5a6c 100644 --- a/api/agent/call.go +++ b/api/agent/call.go @@ -45,11 +45,11 @@ type CallOverrider func(*http.Request, *models.Call, map[string]string) (map[str // CallOpt allows configuring a call before execution // TODO(reed): consider the interface here, all options must be defined in agent and flexible // enough for usage by extenders of fn, this straddling is painful. consider models.Call? -type CallOpt func(c *call) error +type CallOpt func(Config, *call) error // FromHTTPFnRequest Sets up a call from an http trigger request func FromHTTPFnRequest(app *models.App, fn *models.Fn, req *http.Request) CallOpt { - return func(c *call) error { + return func(cfg Config, c *call) error { id := id.New().String() var syslogURL string @@ -121,7 +121,7 @@ func reqURL(req *http.Request) string { // FromModel creates a call object from an existing stored call model object, reading the body from the stored call payload func FromModel(mCall *models.Call) CallOpt { - return func(c *call) error { + return func(cfg Config, c *call) error { c.Call = mCall req, err := http.NewRequest(c.Method, c.URL, strings.NewReader(c.Payload)) @@ -138,7 +138,7 @@ func FromModel(mCall *models.Call) CallOpt { // FromModelAndInput creates a call object from an existing stored call model object , reading the body from a provided stream func FromModelAndInput(mCall *models.Call, in io.ReadCloser) CallOpt { - return func(c *call) error { + return func(cfg Config, c *call) error { c.Call = mCall req, err := http.NewRequest(c.Method, c.URL, in) @@ -156,7 +156,7 @@ func FromModelAndInput(mCall *models.Call, in io.ReadCloser) CallOpt { // WithTrigger adds trigger specific bits to a call. // TODO consider removal, this is from a shuffle func WithTrigger(t *models.Trigger) CallOpt { - return func(c *call) error { + return func(cfg Config, c *call) error { // right now just set the trigger id c.TriggerID = t.ID return nil @@ -166,7 +166,7 @@ func WithTrigger(t *models.Trigger) CallOpt { // WithWriter sets the writer that the call uses to send its output message to // TODO this should be required func WithWriter(w io.Writer) CallOpt { - return func(c *call) error { + return func(cfg Config, c *call) error { c.respWriter = w return nil } @@ -174,7 +174,7 @@ func WithWriter(w io.Writer) CallOpt { // WithLogger sets stderr to the provided one func WithLogger(w io.ReadWriteCloser) CallOpt { - return func(c *call) error { + return func(cfg Config, c *call) error { c.stderr = w return nil } @@ -182,7 +182,7 @@ func WithLogger(w io.ReadWriteCloser) CallOpt { // InvokeDetached mark a call to be a detached call func InvokeDetached() CallOpt { - return func(c *call) error { + return func(cfg Config, c *call) error { c.Model().Type = models.TypeDetached return nil } @@ -190,7 +190,7 @@ func InvokeDetached() CallOpt { // WithContext overrides the context on the call func WithContext(ctx context.Context) CallOpt { - return func(c *call) error { + return func(cfg Config, c *call) error { c.req = c.req.WithContext(ctx) return nil } @@ -199,7 +199,7 @@ func WithContext(ctx context.Context) CallOpt { // WithExtensions adds internal attributes to the call that can be interpreted by extensions in the agent // Pure runner can use this to pass an extension to the call func WithExtensions(extensions map[string]string) CallOpt { - return func(c *call) error { + return func(cfg Config, c *call) error { c.extensions = extensions return nil } @@ -207,7 +207,7 @@ func WithExtensions(extensions map[string]string) CallOpt { // WithDockerAuth configures a call to retrieve credentials for an image pull func WithDockerAuth(auth docker.Auther) CallOpt { - return func(c *call) error { + return func(cfg Config, c *call) error { c.dockerAuth = auth return nil } @@ -217,13 +217,12 @@ func WithDockerAuth(auth docker.Auther) CallOpt { // Configure UserLogLevel or DisableDebugUserLogs on agent to change behavior. func WithStderrLogger() CallOpt { // TODO(reed): we could take a context here which would allow request level logging vars on ctx to be used here too - return func(c *call) error { - // TODO(reed): fucking hell this is a pain to configure - if a.cfg.DisableDebugUserLogs { + return func(cfg Config, c *call) error { + if cfg.DisableDebugUserLogs { return nil } - c.stderr = setupLogger(a.cfg.UserLogLevel, c.Call) + c.stderr = setupLogger(c.Call, cfg.UserLogLevel) return nil } } @@ -238,7 +237,7 @@ func (a *agent) GetCall(opts ...CallOpt) (Call, error) { opts = append(opts, a.callOpts...) for _, o := range opts { - err := o(&c) + err := o(a.cfg, &c) if err != nil { return nil, err } diff --git a/api/agent/func_logger.go b/api/agent/func_logger.go index 6ea7df38b8..1503d179a2 100644 --- a/api/agent/func_logger.go +++ b/api/agent/func_logger.go @@ -14,8 +14,8 @@ var ( bufPool = &sync.Pool{New: func() interface{} { return new(bytes.Buffer) }} ) -// * [always] writes bytes per line to stderr as DEBUG -func setupLogger(level string, c *models.Call) io.WriteCloser { +// the returned writer writes bytes per line to stderr +func setupLogger(c *models.Call, level string) io.WriteCloser { lbuf := bufPool.Get().(*bytes.Buffer) close := func() { @@ -27,14 +27,14 @@ func setupLogger(level string, c *models.Call) io.WriteCloser { stderrLogger := logrus.WithFields(logrus.Fields{"user_log": true, "app_id": c.AppID, "fn_id": c.FnID, "image": c.Image, "call_id": c.ID}) loggo := newLogWriter(stderrLogger, level) linew := newLineWriterWithBuffer(lbuf, loggo) - linew = &fCloser{ + return &fCloser{ + Writer: linew, close: func() error { err := linew.Close() close() return err }, } - return linew } // implements passthrough WriteCloser with overwritable Close diff --git a/api/agent/lb_agent.go b/api/agent/lb_agent.go index aee258cbb8..b4c65e7598 100644 --- a/api/agent/lb_agent.go +++ b/api/agent/lb_agent.go @@ -149,7 +149,7 @@ func (a *lbAgent) GetCall(opts ...CallOpt) (Call, error) { opts = append(opts, a.callOpts...) for _, o := range opts { - err := o(&c) + err := o(a.cfg, &c) if err != nil { return nil, err } diff --git a/api/server/runner_fninvoke.go b/api/server/runner_fninvoke.go index 06931d1b0d..2144b7b6da 100644 --- a/api/server/runner_fninvoke.go +++ b/api/server/runner_fninvoke.go @@ -144,6 +144,3 @@ func (s *Server) fnInvoke(resp http.ResponseWriter, req *http.Request, app *mode bufPool.Put(buf) // at this point, submit returned without timing out, so we can re-use this one return nil } - -func getCallOptions(req *http.Request, app *models.App, fn *models.Fn, trig *models.Trigger, rw http.ResponseWriter) []agent.CallOpt { -} From 047591b43c3425dd2c6e2aa37ae0cb3427168653 Mon Sep 17 00:00:00 2001 From: Reed Allman Date: Thu, 18 Apr 2019 06:56:51 -0700 Subject: [PATCH 6/9] fix tests --- api/agent/lb_agent_test.go | 4 ++-- api/server/runner_fninvoke_test.go | 2 +- api/server/runner_httptrigger_test.go | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/api/agent/lb_agent_test.go b/api/agent/lb_agent_test.go index b8b20ce468..44927139d4 100644 --- a/api/agent/lb_agent_test.go +++ b/api/agent/lb_agent_test.go @@ -269,7 +269,7 @@ func TestEnforceLbTimeout(t *testing.T) { // SetCallType create a models.Call setting up the provided Call Type func SetCallType(callType string) CallOpt { - return func(c *call) error { + return func(cfg Config, c *call) error { c.Call = &models.Call{Type: callType} c.req, _ = http.NewRequest("GET", "http://www.example.com", nil) return nil @@ -277,7 +277,7 @@ func SetCallType(callType string) CallOpt { } func ModifyCallRequest(callType string) CallOpt { - return func(c *call) error { + return func(cfg Config, c *call) error { c.Call.Type = callType return nil } diff --git a/api/server/runner_fninvoke_test.go b/api/server/runner_fninvoke_test.go index 8c364753f9..906f7b46bb 100644 --- a/api/server/runner_fninvoke_test.go +++ b/api/server/runner_fninvoke_test.go @@ -218,7 +218,7 @@ func TestFnInvokeRunnerExecution(t *testing.T) { {"/invoke/http_stream_fn_id", oomer, nil, http.MethodPost, http.StatusBadGateway, nil, "error receiving function response", nil}, {"/invoke/http_stream_fn_id", bigbuf, nil, http.MethodPost, http.StatusRequestEntityTooLarge, nil, "", nil}, - {"/invoke/dne_fn_id", ``, nil, http.MethodPost, http.StatusNotFound, nil, "pull access denied", nil}, + {"/invoke/dne_fn_id", ``, nil, http.MethodPost, http.StatusNotFound, nil, "Failed to pull image", nil}, {"/invoke/dnereg_fn_id", ``, nil, http.MethodPost, http.StatusBadGateway, nil, "connection refused", nil}, // XXX(reed): nil, nil, what are these? diff --git a/api/server/runner_httptrigger_test.go b/api/server/runner_httptrigger_test.go index 5c18ab8221..b7aa41fa78 100644 --- a/api/server/runner_httptrigger_test.go +++ b/api/server/runner_httptrigger_test.go @@ -301,7 +301,7 @@ func TestTriggerRunnerExecution(t *testing.T) { // XXX(reed): meh we really should try to get oom out, but maybe it's better left to the logs? {"/t/myapp/httpstream", nil, oomer, "POST", http.StatusBadGateway, nil, "error receiving function response", nil}, - {"/t/myapp/mydne", nil, ``, "GET", http.StatusNotFound, nil, "pull access denied", nil}, + {"/t/myapp/mydne", nil, ``, "GET", http.StatusNotFound, nil, "Failed to pull image", nil}, {"/t/myapp/mydneregistry", nil, ``, "GET", http.StatusBadGateway, nil, "connection refused", nil}, // XXX(reed): what are these? From c00c62079a39af37f63e9769cc54fd6282837a82 Mon Sep 17 00:00:00 2001 From: Reed Allman Date: Thu, 18 Apr 2019 07:59:19 -0700 Subject: [PATCH 7/9] remove another todo --- api/agent/agent.go | 1 - 1 file changed, 1 deletion(-) diff --git a/api/agent/agent.go b/api/agent/agent.go index 71e2297436..4e582eddf7 100644 --- a/api/agent/agent.go +++ b/api/agent/agent.go @@ -644,7 +644,6 @@ func (s *hotSlot) dispatch(ctx context.Context, call *call) error { ctx, span := trace.StartSpan(ctx, "agent_dispatch_httpstream") defer span.End() - // TODO it's possible we can get rid of this (after getting rid of logs API) - may need for call id/debug mode still swapBack := s.container.swap(call.stderr, &call.Stats) defer call.stderr.Close() defer swapBack() From dbc2c166f28da4849b69c8c6f806174b1f9dcd60 Mon Sep 17 00:00:00 2001 From: Reed Allman Date: Thu, 9 May 2019 12:46:40 -0700 Subject: [PATCH 8/9] fix func logger and add test --- api/agent/func_logger.go | 12 +++++---- api/agent/func_logger_test.go | 49 +++++++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+), 5 deletions(-) create mode 100644 api/agent/func_logger_test.go diff --git a/api/agent/func_logger.go b/api/agent/func_logger.go index 1503d179a2..486ab78e0b 100644 --- a/api/agent/func_logger.go +++ b/api/agent/func_logger.go @@ -111,18 +111,20 @@ func (li *lineWriter) Write(ogb []byte) (int, error) { var n int for { - // read the line and advance buffer past it - l, err := li.b.ReadBytes('\n') - if err != nil { - break // no more newlines in buffer (see ReadBytes contract) + b := li.b.Bytes() + i := bytes.IndexByte(b, '\n') + if i < 0 { + break // no more newlines in buffer } - // write in the line + // write in this line and advance buffer past it + l := b[:i+1] ns, err := li.w.Write(l) n += ns if err != nil { return n, err } + li.b.Next(len(l)) } // technically we wrote all the bytes, so make things appear normal diff --git a/api/agent/func_logger_test.go b/api/agent/func_logger_test.go new file mode 100644 index 0000000000..acf01ab52c --- /dev/null +++ b/api/agent/func_logger_test.go @@ -0,0 +1,49 @@ +package agent + +import ( + "bytes" + "fmt" + "testing" +) + +type testSliceWriter struct { + b [][]byte +} + +func (tsw *testSliceWriter) Write(p []byte) (n int, err error) { + l := make([]byte, len(p)) + copy(l, p) + tsw.b = append(tsw.b, l) + return len(p), nil +} + +func TestLineWriter(t *testing.T) { + var tsw testSliceWriter + lw := newLineWriter(&nopCloser{&tsw}) + + lineCount := 7 + lw.Write([]byte("0 line\n1 line\n2 line\n\n4 line")) + lw.Write([]byte("+more\n5 line\n")) + lw.Write([]byte("6 line")) + + lw.Close() + + if len(tsw.b) != lineCount { + t.Errorf("Expected %v individual rows; got %v", lineCount, len(tsw.b)) + } + + for x := 0; x < len(tsw.b); x++ { + l := fmt.Sprintf("%v line\n", x) + if x == 3 { + if len(tsw.b[x]) != 1 { + t.Errorf("Expected slice with only newline; got %v", tsw.b[x]) + } + continue + } else if x == 4 { + l = "4 line+more\n" + } + if !bytes.Equal(tsw.b[x], []byte(l)) { + t.Errorf("Expected slice %s equal to %s", []byte(l), tsw.b[x]) + } + } +} From a48067782017ae22ddf6c43ff4acad3ede2b59fb Mon Sep 17 00:00:00 2001 From: Reed Allman Date: Thu, 9 May 2019 22:40:23 -0700 Subject: [PATCH 9/9] clean up short writes / fix incorrect returned n --- api/agent/func_logger.go | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/api/agent/func_logger.go b/api/agent/func_logger.go index 486ab78e0b..fa25fca71a 100644 --- a/api/agent/func_logger.go +++ b/api/agent/func_logger.go @@ -87,7 +87,8 @@ func (l *logWriter) Close() error { // on the underlying writer once per new line. Close must // be called to ensure that the buffer is flushed, and a newline // will be appended in Close if none is present. -// TODO(reed): is line writer is vulnerable to attack? +// NOTE(reed): line writer is susceptible to attacks via logging large lines, +// recommend to disable stderr logs in production anyway. type lineWriter struct { b *bytes.Buffer w io.WriteCloser @@ -107,9 +108,9 @@ func (li *lineWriter) Write(ogb []byte) (int, error) { // we don't want to return 0/error or the container will shut down return len(ogb), nil } + li.b.Write(ogb) // bytes.Buffer is guaranteed, read it! - var n int for { b := li.b.Bytes() i := bytes.IndexByte(b, '\n') @@ -117,14 +118,15 @@ func (li *lineWriter) Write(ogb []byte) (int, error) { break // no more newlines in buffer } - // write in this line and advance buffer past it l := b[:i+1] - ns, err := li.w.Write(l) - n += ns + n, err := li.w.Write(l) + // advance, regardless - if it's a partial write underneath not on a newline, we can't help but the next + // call to write will try to write it again + li.b.Next(n) if err != nil { - return n, err + // we consumed the whole buffer and it may get written eventually + return len(ogb), err } - li.b.Next(len(l)) } // technically we wrote all the bytes, so make things appear normal