[VOL-2235] Mocks and interfaces for rw-core
This update consists of mocks that are used by the rw-core
during unit testing. It also includes interfaces used for unit
tests.
Change-Id: I20ca1455c358113c3aa897acc6355e0ddbc614b7
diff --git a/vendor/go.etcd.io/etcd/embed/config_logging.go b/vendor/go.etcd.io/etcd/embed/config_logging.go
new file mode 100644
index 0000000..e42103c
--- /dev/null
+++ b/vendor/go.etcd.io/etcd/embed/config_logging.go
@@ -0,0 +1,312 @@
+// Copyright 2018 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package embed
+
+import (
+ "crypto/tls"
+ "errors"
+ "fmt"
+ "io/ioutil"
+ "os"
+ "reflect"
+ "sync"
+
+ "go.etcd.io/etcd/pkg/logutil"
+
+ "github.com/coreos/pkg/capnslog"
+ "go.uber.org/zap"
+ "go.uber.org/zap/zapcore"
+ "google.golang.org/grpc"
+ "google.golang.org/grpc/grpclog"
+)
+
+// GetLogger returns the logger.
+func (cfg Config) GetLogger() *zap.Logger {
+ cfg.loggerMu.RLock()
+ l := cfg.logger
+ cfg.loggerMu.RUnlock()
+ return l
+}
+
+// for testing
+var grpcLogOnce = new(sync.Once)
+
+// setupLogging initializes etcd logging.
+// Must be called after flag parsing or finishing configuring embed.Config.
+func (cfg *Config) setupLogging() error {
+ // handle "DeprecatedLogOutput" in v3.4
+ // TODO: remove "DeprecatedLogOutput" in v3.5
+ len1 := len(cfg.DeprecatedLogOutput)
+ len2 := len(cfg.LogOutputs)
+ if len1 != len2 {
+ switch {
+ case len1 > len2: // deprecate "log-output" flag is used
+ fmt.Fprintln(os.Stderr, "'--log-output' flag has been deprecated! Please use '--log-outputs'!")
+ cfg.LogOutputs = cfg.DeprecatedLogOutput
+ case len1 < len2: // "--log-outputs" flag has been set with multiple writers
+ cfg.DeprecatedLogOutput = []string{}
+ }
+ } else {
+ if len1 > 1 {
+ return errors.New("both '--log-output' and '--log-outputs' are set; only set '--log-outputs'")
+ }
+ if len1 < 1 {
+ return errors.New("either '--log-output' or '--log-outputs' flag must be set")
+ }
+ if reflect.DeepEqual(cfg.DeprecatedLogOutput, cfg.LogOutputs) && cfg.DeprecatedLogOutput[0] != DefaultLogOutput {
+ return fmt.Errorf("'--log-output=%q' and '--log-outputs=%q' are incompatible; only set --log-outputs", cfg.DeprecatedLogOutput, cfg.LogOutputs)
+ }
+ if !reflect.DeepEqual(cfg.DeprecatedLogOutput, []string{DefaultLogOutput}) {
+ fmt.Fprintf(os.Stderr, "[WARNING] Deprecated '--log-output' flag is set to %q\n", cfg.DeprecatedLogOutput)
+ fmt.Fprintln(os.Stderr, "Please use '--log-outputs' flag")
+ }
+ }
+
+ // TODO: remove after deprecating log related flags in v3.5
+ if cfg.Debug {
+ fmt.Fprintf(os.Stderr, "[WARNING] Deprecated '--debug' flag is set to %v (use '--log-level=debug' instead\n", cfg.Debug)
+ }
+ if cfg.Debug && cfg.LogLevel != "debug" {
+ fmt.Fprintf(os.Stderr, "[WARNING] Deprecated '--debug' flag is set to %v with inconsistent '--log-level=%s' flag\n", cfg.Debug, cfg.LogLevel)
+ }
+ if cfg.Logger == "capnslog" {
+ fmt.Fprintf(os.Stderr, "[WARNING] Deprecated '--logger=%s' flag is set; use '--logger=zap' flag instead\n", cfg.Logger)
+ }
+ if cfg.LogPkgLevels != "" {
+ fmt.Fprintf(os.Stderr, "[WARNING] Deprecated '--log-package-levels=%s' flag is set; use '--logger=zap' flag instead\n", cfg.LogPkgLevels)
+ }
+
+ switch cfg.Logger {
+ case "capnslog": // TODO: deprecate this in v3.5
+ cfg.ClientTLSInfo.HandshakeFailure = logTLSHandshakeFailure
+ cfg.PeerTLSInfo.HandshakeFailure = logTLSHandshakeFailure
+
+ if cfg.Debug {
+ capnslog.SetGlobalLogLevel(capnslog.DEBUG)
+ grpc.EnableTracing = true
+ // enable info, warning, error
+ grpclog.SetLoggerV2(grpclog.NewLoggerV2(os.Stderr, os.Stderr, os.Stderr))
+ } else {
+ capnslog.SetGlobalLogLevel(logutil.ConvertToCapnslogLogLevel(cfg.LogLevel))
+ // only discard info
+ grpclog.SetLoggerV2(grpclog.NewLoggerV2(ioutil.Discard, os.Stderr, os.Stderr))
+ }
+
+ // TODO: deprecate with "capnslog"
+ if cfg.LogPkgLevels != "" {
+ repoLog := capnslog.MustRepoLogger("go.etcd.io/etcd")
+ settings, err := repoLog.ParseLogLevelConfig(cfg.LogPkgLevels)
+ if err != nil {
+ plog.Warningf("couldn't parse log level string: %s, continuing with default levels", err.Error())
+ return nil
+ }
+ repoLog.SetLogLevel(settings)
+ }
+
+ if len(cfg.LogOutputs) != 1 {
+ return fmt.Errorf("--logger=capnslog supports only 1 value in '--log-outputs', got %q", cfg.LogOutputs)
+ }
+ // capnslog initially SetFormatter(NewDefaultFormatter(os.Stderr))
+ // where NewDefaultFormatter returns NewJournaldFormatter when syscall.Getppid() == 1
+ // specify 'stdout' or 'stderr' to skip journald logging even when running under systemd
+ output := cfg.LogOutputs[0]
+ switch output {
+ case StdErrLogOutput:
+ capnslog.SetFormatter(capnslog.NewPrettyFormatter(os.Stderr, cfg.Debug))
+ case StdOutLogOutput:
+ capnslog.SetFormatter(capnslog.NewPrettyFormatter(os.Stdout, cfg.Debug))
+ case DefaultLogOutput:
+ default:
+ return fmt.Errorf("unknown log-output %q (only supports %q, %q, %q)", output, DefaultLogOutput, StdErrLogOutput, StdOutLogOutput)
+ }
+
+ case "zap":
+ if len(cfg.LogOutputs) == 0 {
+ cfg.LogOutputs = []string{DefaultLogOutput}
+ }
+ if len(cfg.LogOutputs) > 1 {
+ for _, v := range cfg.LogOutputs {
+ if v == DefaultLogOutput {
+ return fmt.Errorf("multi logoutput for %q is not supported yet", DefaultLogOutput)
+ }
+ }
+ }
+
+ outputPaths, errOutputPaths := make([]string, 0), make([]string, 0)
+ isJournal := false
+ for _, v := range cfg.LogOutputs {
+ switch v {
+ case DefaultLogOutput:
+ outputPaths = append(outputPaths, StdErrLogOutput)
+ errOutputPaths = append(errOutputPaths, StdErrLogOutput)
+
+ case JournalLogOutput:
+ isJournal = true
+
+ case StdErrLogOutput:
+ outputPaths = append(outputPaths, StdErrLogOutput)
+ errOutputPaths = append(errOutputPaths, StdErrLogOutput)
+
+ case StdOutLogOutput:
+ outputPaths = append(outputPaths, StdOutLogOutput)
+ errOutputPaths = append(errOutputPaths, StdOutLogOutput)
+
+ default:
+ outputPaths = append(outputPaths, v)
+ errOutputPaths = append(errOutputPaths, v)
+ }
+ }
+
+ if !isJournal {
+ copied := logutil.DefaultZapLoggerConfig
+ copied.OutputPaths = outputPaths
+ copied.ErrorOutputPaths = errOutputPaths
+ copied = logutil.MergeOutputPaths(copied)
+ copied.Level = zap.NewAtomicLevelAt(logutil.ConvertToZapLevel(cfg.LogLevel))
+ if cfg.Debug || cfg.LogLevel == "debug" {
+ // enable tracing even when "--debug --log-level info"
+ // in order to keep backward compatibility with <= v3.3
+ // TODO: remove "Debug" check in v3.5
+ grpc.EnableTracing = true
+ }
+ if cfg.ZapLoggerBuilder == nil {
+ cfg.ZapLoggerBuilder = func(c *Config) error {
+ var err error
+ c.logger, err = copied.Build()
+ if err != nil {
+ return err
+ }
+ c.loggerMu.Lock()
+ defer c.loggerMu.Unlock()
+ c.loggerConfig = &copied
+ c.loggerCore = nil
+ c.loggerWriteSyncer = nil
+ grpcLogOnce.Do(func() {
+ // debug true, enable info, warning, error
+ // debug false, only discard info
+ var gl grpclog.LoggerV2
+ gl, err = logutil.NewGRPCLoggerV2(copied)
+ if err == nil {
+ grpclog.SetLoggerV2(gl)
+ }
+ })
+ return nil
+ }
+ }
+ } else {
+ if len(cfg.LogOutputs) > 1 {
+ for _, v := range cfg.LogOutputs {
+ if v != DefaultLogOutput {
+ return fmt.Errorf("running with systemd/journal but other '--log-outputs' values (%q) are configured with 'default'; override 'default' value with something else", cfg.LogOutputs)
+ }
+ }
+ }
+
+ // use stderr as fallback
+ syncer, lerr := getJournalWriteSyncer()
+ if lerr != nil {
+ return lerr
+ }
+
+ lvl := zap.NewAtomicLevelAt(logutil.ConvertToZapLevel(cfg.LogLevel))
+ if cfg.Debug || cfg.LogLevel == "debug" {
+ // enable tracing even when "--debug --log-level info"
+ // in order to keep backward compatibility with <= v3.3
+ // TODO: remove "Debug" check in v3.5
+ grpc.EnableTracing = true
+ }
+
+ // WARN: do not change field names in encoder config
+ // journald logging writer assumes field names of "level" and "caller"
+ cr := zapcore.NewCore(
+ zapcore.NewJSONEncoder(logutil.DefaultZapLoggerConfig.EncoderConfig),
+ syncer,
+ lvl,
+ )
+ if cfg.ZapLoggerBuilder == nil {
+ cfg.ZapLoggerBuilder = func(c *Config) error {
+ c.logger = zap.New(cr, zap.AddCaller(), zap.ErrorOutput(syncer))
+ c.loggerMu.Lock()
+ defer c.loggerMu.Unlock()
+ c.loggerConfig = nil
+ c.loggerCore = cr
+ c.loggerWriteSyncer = syncer
+
+ grpcLogOnce.Do(func() {
+ grpclog.SetLoggerV2(logutil.NewGRPCLoggerV2FromZapCore(cr, syncer))
+ })
+ return nil
+ }
+ }
+ }
+
+ err := cfg.ZapLoggerBuilder(cfg)
+ if err != nil {
+ return err
+ }
+
+ logTLSHandshakeFailure := func(conn *tls.Conn, err error) {
+ state := conn.ConnectionState()
+ remoteAddr := conn.RemoteAddr().String()
+ serverName := state.ServerName
+ if len(state.PeerCertificates) > 0 {
+ cert := state.PeerCertificates[0]
+ ips := make([]string, len(cert.IPAddresses))
+ for i := range cert.IPAddresses {
+ ips[i] = cert.IPAddresses[i].String()
+ }
+ cfg.logger.Warn(
+ "rejected connection",
+ zap.String("remote-addr", remoteAddr),
+ zap.String("server-name", serverName),
+ zap.Strings("ip-addresses", ips),
+ zap.Strings("dns-names", cert.DNSNames),
+ zap.Error(err),
+ )
+ } else {
+ cfg.logger.Warn(
+ "rejected connection",
+ zap.String("remote-addr", remoteAddr),
+ zap.String("server-name", serverName),
+ zap.Error(err),
+ )
+ }
+ }
+ cfg.ClientTLSInfo.HandshakeFailure = logTLSHandshakeFailure
+ cfg.PeerTLSInfo.HandshakeFailure = logTLSHandshakeFailure
+
+ default:
+ return fmt.Errorf("unknown logger option %q", cfg.Logger)
+ }
+
+ return nil
+}
+
+// NewZapCoreLoggerBuilder generates a zap core logger builder.
+func NewZapCoreLoggerBuilder(lg *zap.Logger, cr zapcore.Core, syncer zapcore.WriteSyncer) func(*Config) error {
+ return func(cfg *Config) error {
+ cfg.loggerMu.Lock()
+ defer cfg.loggerMu.Unlock()
+ cfg.logger = lg
+ cfg.loggerConfig = nil
+ cfg.loggerCore = cr
+ cfg.loggerWriteSyncer = syncer
+
+ grpcLogOnce.Do(func() {
+ grpclog.SetLoggerV2(logutil.NewGRPCLoggerV2FromZapCore(cr, syncer))
+ })
+ return nil
+ }
+}