Add logger interface and stop relying on Logrus directly

This commit is contained in:
Mark Sagi-Kazar
2019-02-22 13:38:57 +01:00
parent ca66289077
commit be581fa7ff
38 changed files with 203 additions and 133 deletions
+2 -2
View File
@@ -6,9 +6,9 @@ import (
"fmt"
"os"
"github.com/sirupsen/logrus"
"golang.org/x/crypto/bcrypt"
"github.com/dexidp/dex/pkg/log"
"github.com/dexidp/dex/server"
"github.com/dexidp/dex/storage"
"github.com/dexidp/dex/storage/etcd"
@@ -127,7 +127,7 @@ type Storage struct {
// StorageConfig is a configuration that can create a storage.
type StorageConfig interface {
Open(logrus.FieldLogger) (storage.Storage, error)
Open(logger log.Logger) (storage.Storage, error)
}
var storages = map[string]func() StorageConfig{
+4 -3
View File
@@ -23,6 +23,7 @@ import (
"google.golang.org/grpc/credentials"
"github.com/dexidp/dex/api"
"github.com/dexidp/dex/pkg/log"
"github.com/dexidp/dex/server"
"github.com/dexidp/dex/storage"
)
@@ -324,7 +325,7 @@ func (f *utcFormatter) Format(e *logrus.Entry) ([]byte, error) {
return f.f.Format(e)
}
func newLogger(level string, format string) (logrus.FieldLogger, error) {
func newLogger(level string, format string) (log.Logger, error) {
var logLevel logrus.Level
switch strings.ToLower(level) {
case "debug":
@@ -347,9 +348,9 @@ func newLogger(level string, format string) (logrus.FieldLogger, error) {
return nil, fmt.Errorf("log format is not one of the supported values (%s): %s", strings.Join(logFormats, ", "), format)
}
return &logrus.Logger{
return log.NewLogrusLogger(&logrus.Logger{
Out: os.Stderr,
Formatter: &formatter,
Level: logLevel,
}, nil
}), nil
}
+3 -4
View File
@@ -8,9 +8,8 @@ import (
"net/http"
"net/url"
"github.com/sirupsen/logrus"
"github.com/dexidp/dex/connector"
"github.com/dexidp/dex/pkg/log"
)
// Config holds the configuration parameters for a connector which returns an
@@ -18,14 +17,14 @@ import (
type Config struct{}
// Open returns an authentication strategy which requires no user interaction.
func (c *Config) Open(id string, logger logrus.FieldLogger) (connector.Connector, error) {
func (c *Config) Open(id string, logger log.Logger) (connector.Connector, error) {
return &callback{logger: logger, pathSuffix: "/" + id}, nil
}
// Callback is a connector which returns an identity with the HTTP header
// X-Remote-User as verified email.
type callback struct {
logger logrus.FieldLogger
logger log.Logger
pathSuffix string
}
+3 -4
View File
@@ -6,6 +6,7 @@ import (
"encoding/json"
"errors"
"fmt"
"github.com/dexidp/dex/pkg/log"
"io/ioutil"
"net/http"
"sync"
@@ -14,8 +15,6 @@ import (
"golang.org/x/oauth2"
"golang.org/x/oauth2/bitbucket"
"github.com/sirupsen/logrus"
"github.com/dexidp/dex/connector"
)
@@ -40,7 +39,7 @@ type Config struct {
}
// Open returns a strategy for logging in through Bitbucket.
func (c *Config) Open(id string, logger logrus.FieldLogger) (connector.Connector, error) {
func (c *Config) Open(id string, logger log.Logger) (connector.Connector, error) {
b := bitbucketConnector{
redirectURI: c.RedirectURI,
@@ -70,7 +69,7 @@ type bitbucketConnector struct {
teams []string
clientID string
clientSecret string
logger logrus.FieldLogger
logger log.Logger
apiURL string
// the following are used only for tests
+4 -5
View File
@@ -16,11 +16,11 @@ import (
"strings"
"time"
"github.com/sirupsen/logrus"
"golang.org/x/oauth2"
"golang.org/x/oauth2/github"
"github.com/dexidp/dex/connector"
"github.com/dexidp/dex/pkg/log"
)
const (
@@ -53,7 +53,6 @@ type Config struct {
// Org holds org-team filters, in which teams are optional.
type Org struct {
// Organization name in github (not slug, full name). Only users in this github
// organization can authenticate.
Name string `json:"name"`
@@ -66,14 +65,14 @@ type Org struct {
}
// Open returns a strategy for logging in through GitHub.
func (c *Config) Open(id string, logger logrus.FieldLogger) (connector.Connector, error) {
func (c *Config) Open(id string, logger log.Logger) (connector.Connector, error) {
if c.Org != "" {
// Return error if both 'org' and 'orgs' fields are used.
if len(c.Orgs) > 0 {
return nil, errors.New("github: cannot use both 'org' and 'orgs' fields simultaneously")
}
logger.Warnln("github: legacy field 'org' being used. Switch to the newer 'orgs' field structure")
logger.Warn("github: legacy field 'org' being used. Switch to the newer 'orgs' field structure")
}
g := githubConnector{
@@ -137,7 +136,7 @@ type githubConnector struct {
orgs []Org
clientID string
clientSecret string
logger logrus.FieldLogger
logger log.Logger
// apiURL defaults to "https://api.github.com"
apiURL string
// hostName of the GitHub enterprise account.
+3 -3
View File
@@ -10,10 +10,10 @@ import (
"net/http"
"strconv"
"github.com/sirupsen/logrus"
"golang.org/x/oauth2"
"github.com/dexidp/dex/connector"
"github.com/dexidp/dex/pkg/log"
)
const (
@@ -42,7 +42,7 @@ type gitlabUser struct {
}
// Open returns a strategy for logging in through GitLab.
func (c *Config) Open(id string, logger logrus.FieldLogger) (connector.Connector, error) {
func (c *Config) Open(id string, logger log.Logger) (connector.Connector, error) {
if c.BaseURL == "" {
c.BaseURL = "https://gitlab.com"
}
@@ -71,7 +71,7 @@ type gitlabConnector struct {
org string
clientID string
clientSecret string
logger logrus.FieldLogger
logger log.Logger
}
func (c *gitlabConnector) oauth2Config(scopes connector.Scopes) *oauth2.Config {
+3 -4
View File
@@ -9,9 +9,8 @@ import (
"io/ioutil"
"net/http"
"github.com/sirupsen/logrus"
"github.com/dexidp/dex/connector"
"github.com/dexidp/dex/pkg/log"
)
type conn struct {
@@ -19,7 +18,7 @@ type conn struct {
Host string
AdminUsername string
AdminPassword string
Logger logrus.FieldLogger
Logger log.Logger
}
type userKeystone struct {
@@ -102,7 +101,7 @@ var (
)
// Open returns an authentication strategy using Keystone.
func (c *Config) Open(id string, logger logrus.FieldLogger) (connector.Connector, error) {
func (c *Config) Open(id string, logger log.Logger) (connector.Connector, error) {
return &conn{
c.Domain,
c.Host,
+5 -6
View File
@@ -12,9 +12,8 @@ import (
"gopkg.in/ldap.v2"
"github.com/sirupsen/logrus"
"github.com/dexidp/dex/connector"
"github.com/dexidp/dex/pkg/log"
)
// Config holds the configuration parameters for the LDAP connector. The LDAP
@@ -165,7 +164,7 @@ func parseScope(s string) (int, bool) {
}
// Open returns an authentication strategy using LDAP.
func (c *Config) Open(id string, logger logrus.FieldLogger) (connector.Connector, error) {
func (c *Config) Open(id string, logger log.Logger) (connector.Connector, error) {
conn, err := c.OpenConnector(logger)
if err != nil {
return nil, err
@@ -179,7 +178,7 @@ type refreshData struct {
}
// OpenConnector is the same as Open but returns a type with all implemented connector interfaces.
func (c *Config) OpenConnector(logger logrus.FieldLogger) (interface {
func (c *Config) OpenConnector(logger log.Logger) (interface {
connector.Connector
connector.PasswordConnector
connector.RefreshConnector
@@ -187,7 +186,7 @@ func (c *Config) OpenConnector(logger logrus.FieldLogger) (interface {
return c.openConnector(logger)
}
func (c *Config) openConnector(logger logrus.FieldLogger) (*ldapConnector, error) {
func (c *Config) openConnector(logger log.Logger) (*ldapConnector, error) {
requiredFields := []struct {
name string
@@ -259,7 +258,7 @@ type ldapConnector struct {
tlsConfig *tls.Config
logger logrus.FieldLogger
logger log.Logger
}
var (
+2 -1
View File
@@ -17,6 +17,7 @@ import (
"github.com/sirupsen/logrus"
"github.com/dexidp/dex/connector"
"github.com/dexidp/dex/pkg/log"
)
const envVar = "DEX_LDAP_TESTS"
@@ -875,7 +876,7 @@ func runTests(t *testing.T, schema string, connMethod connectionMethod, config *
c.BindDN = "cn=admin,dc=example,dc=org"
c.BindPW = "admin"
l := &logrus.Logger{Out: ioutil.Discard, Formatter: &logrus.TextFormatter{}}
l := log.NewLogrusLogger(&logrus.Logger{Out: ioutil.Discard, Formatter: &logrus.TextFormatter{}})
conn, err := c.openConnector(l)
if err != nil {
+3 -4
View File
@@ -11,9 +11,8 @@ import (
"golang.org/x/oauth2"
"github.com/sirupsen/logrus"
"github.com/dexidp/dex/connector"
"github.com/dexidp/dex/pkg/log"
)
const (
@@ -30,7 +29,7 @@ type Config struct {
}
// Open returns a strategy for logging in through LinkedIn
func (c *Config) Open(id string, logger logrus.FieldLogger) (connector.Connector, error) {
func (c *Config) Open(id string, logger log.Logger) (connector.Connector, error) {
return &linkedInConnector{
oauth2Config: &oauth2.Config{
ClientID: c.ClientID,
@@ -52,7 +51,7 @@ type connectorData struct {
type linkedInConnector struct {
oauth2Config *oauth2.Config
logger logrus.FieldLogger
logger log.Logger
}
// LinkedIn doesn't provide refresh tokens, so refresh tokens issued by Dex
+3 -4
View File
@@ -14,9 +14,8 @@ import (
"golang.org/x/oauth2"
"github.com/sirupsen/logrus"
"github.com/dexidp/dex/connector"
"github.com/dexidp/dex/pkg/log"
)
const (
@@ -39,7 +38,7 @@ type Config struct {
}
// Open returns a strategy for logging in through Microsoft.
func (c *Config) Open(id string, logger logrus.FieldLogger) (connector.Connector, error) {
func (c *Config) Open(id string, logger log.Logger) (connector.Connector, error) {
m := microsoftConnector{
redirectURI: c.RedirectURI,
clientID: c.ClientID,
@@ -76,7 +75,7 @@ type microsoftConnector struct {
tenant string
onlySecurityGroups bool
groups []string
logger logrus.FieldLogger
logger log.Logger
}
func (c *microsoftConnector) isOrgTenant() bool {
+6 -7
View File
@@ -8,14 +8,13 @@ import (
"net/http"
"net/url"
"github.com/sirupsen/logrus"
"github.com/dexidp/dex/connector"
"github.com/dexidp/dex/pkg/log"
)
// NewCallbackConnector returns a mock connector which requires no user interaction. It always returns
// the same (fake) identity.
func NewCallbackConnector(logger logrus.FieldLogger) connector.Connector {
func NewCallbackConnector(logger log.Logger) connector.Connector {
return &Callback{
Identity: connector.Identity{
UserID: "0-385-28089-0",
@@ -40,7 +39,7 @@ var (
type Callback struct {
// The returned identity.
Identity connector.Identity
Logger logrus.FieldLogger
Logger log.Logger
}
// LoginURL returns the URL to redirect the user to login with.
@@ -71,7 +70,7 @@ func (m *Callback) Refresh(ctx context.Context, s connector.Scopes, identity con
type CallbackConfig struct{}
// Open returns an authentication strategy which requires no user interaction.
func (c *CallbackConfig) Open(id string, logger logrus.FieldLogger) (connector.Connector, error) {
func (c *CallbackConfig) Open(id string, logger log.Logger) (connector.Connector, error) {
return NewCallbackConnector(logger), nil
}
@@ -83,7 +82,7 @@ type PasswordConfig struct {
}
// Open returns an authentication strategy which prompts for a predefined username and password.
func (c *PasswordConfig) Open(id string, logger logrus.FieldLogger) (connector.Connector, error) {
func (c *PasswordConfig) Open(id string, logger log.Logger) (connector.Connector, error) {
if c.Username == "" {
return nil, errors.New("no username supplied")
}
@@ -96,7 +95,7 @@ func (c *PasswordConfig) Open(id string, logger logrus.FieldLogger) (connector.C
type passwordConnector struct {
username string
password string
logger logrus.FieldLogger
logger log.Logger
}
func (p passwordConnector) Close() error { return nil }
+3 -3
View File
@@ -11,10 +11,10 @@ import (
"sync"
"github.com/coreos/go-oidc"
"github.com/sirupsen/logrus"
"golang.org/x/oauth2"
"github.com/dexidp/dex/connector"
"github.com/dexidp/dex/pkg/log"
)
// Config holds configuration options for OpenID Connect logins.
@@ -75,7 +75,7 @@ func registerBrokenAuthHeaderProvider(url string) {
// Open returns a connector which can be used to login users through an upstream
// OpenID Connect provider.
func (c *Config) Open(id string, logger logrus.FieldLogger) (conn connector.Connector, err error) {
func (c *Config) Open(id string, logger log.Logger) (conn connector.Connector, err error) {
ctx, cancel := context.WithCancel(context.Background())
provider, err := oidc.NewProvider(ctx, c.Issuer)
@@ -130,7 +130,7 @@ type oidcConnector struct {
verifier *oidc.IDTokenVerifier
ctx context.Context
cancel context.CancelFunc
logger logrus.FieldLogger
logger log.Logger
hostedDomains []string
}
+5 -6
View File
@@ -14,11 +14,10 @@ import (
"time"
"github.com/beevik/etree"
"github.com/dexidp/dex/connector"
"github.com/dexidp/dex/pkg/log"
dsig "github.com/russellhaering/goxmldsig"
"github.com/russellhaering/goxmldsig/etreeutils"
"github.com/sirupsen/logrus"
"github.com/dexidp/dex/connector"
)
const (
@@ -126,11 +125,11 @@ func (c certStore) Certificates() (roots []*x509.Certificate, err error) {
// Open validates the config and returns a connector. It does not actually
// validate connectivity with the provider.
func (c *Config) Open(id string, logger logrus.FieldLogger) (connector.Connector, error) {
func (c *Config) Open(id string, logger log.Logger) (connector.Connector, error) {
return c.openConnector(logger)
}
func (c *Config) openConnector(logger logrus.FieldLogger) (*provider, error) {
func (c *Config) openConnector(logger log.Logger) (*provider, error) {
requiredFields := []struct {
name, val string
}{
@@ -241,7 +240,7 @@ type provider struct {
nameIDPolicyFormat string
logger logrus.FieldLogger
logger log.Logger
}
func (p *provider) POSTData(s connector.Scopes, id string) (action, value string, err error) {
+4 -3
View File
@@ -5,6 +5,7 @@ import (
"encoding/base64"
"encoding/pem"
"errors"
"github.com/dexidp/dex/pkg/log"
"io/ioutil"
"sort"
"testing"
@@ -304,7 +305,7 @@ func (r responseTest) run(t *testing.T) {
t.Fatalf("parse test time: %v", err)
}
conn, err := c.openConnector(logrus.New())
conn, err := c.openConnector(log.NewLogrusLogger(logrus.New()))
if err != nil {
t.Fatal(err)
}
@@ -338,7 +339,7 @@ func (r responseTest) run(t *testing.T) {
}
func TestConfigCAData(t *testing.T) {
logger := logrus.New()
logger := log.NewLogrusLogger(logrus.New())
validPEM, err := ioutil.ReadFile("testdata/ca.crt")
if err != nil {
t.Fatal(err)
@@ -475,7 +476,7 @@ func newProvider(ssoIssuer string, redirectURI string) *provider {
usernameAttr: "user",
emailAttr: "email",
redirectURI: redirectURI,
logger: logrus.New(),
logger: log.NewLogrusLogger(logrus.New()),
}
}
+17
View File
@@ -0,0 +1,17 @@
// Package log provides a logger interface for logger libraries
// so that dex does not depend on any of them directly.
// It also includes a default implementation using Logrus (used by dex previously).
package log
// Logger serves as an adapter interface for logger libraries
// so that dex does not depend on any of them directly.
type Logger interface {
WithField(key string, value interface{}) Logger
Info(msg string)
Warn(msg string)
Debugf(format string, args ...interface{})
Infof(format string, args ...interface{})
Errorf(format string, args ...interface{})
}
+45
View File
@@ -0,0 +1,45 @@
package log
import "github.com/sirupsen/logrus"
// LogrusLogger is an adapter for Logrus implementing the Logger interface.
type LogrusLogger struct {
logger logrus.FieldLogger
}
// NewLogrusLogger returns a new Logger wrapping Logrus.
func NewLogrusLogger(logger logrus.FieldLogger) *LogrusLogger {
return &LogrusLogger{
logger: logger,
}
}
// WithField adds a field to the log entry.
func (l *LogrusLogger) WithField(key string, value interface{}) Logger {
return NewLogrusLogger(l.logger.WithField(key, value))
}
// Info logs an Info level event.
func (l *LogrusLogger) Info(msg string) {
l.logger.Info(msg)
}
// Warn logs a Warn level event.
func (l *LogrusLogger) Warn(msg string) {
l.logger.Warn(msg)
}
// Debugf formats and logs a Debug level event.
func (l *LogrusLogger) Debugf(format string, args ...interface{}) {
l.logger.Debugf(format, args...)
}
// Infof formats and logs an Info level event.
func (l *LogrusLogger) Infof(format string, args ...interface{}) {
l.logger.Infof(format, args...)
}
// Errorf formats and logs n Error level event.
func (l *LogrusLogger) Errorf(format string, args ...interface{}) {
l.logger.Errorf(format, args...)
}
+10
View File
@@ -0,0 +1,10 @@
package log
import "testing"
func TestLogrusLoggerImplementsLoggerInterface(t *testing.T) {
var i interface{} = new(LogrusLogger)
if _, ok := i.(Logger); !ok {
t.Errorf("expected %T to implement Logger interface", i)
}
}
+3 -4
View File
@@ -10,9 +10,8 @@ import (
// https://github.com/grpc/grpc-go/issues/711
"golang.org/x/net/context"
"github.com/sirupsen/logrus"
"github.com/dexidp/dex/api"
"github.com/dexidp/dex/pkg/log"
"github.com/dexidp/dex/server/internal"
"github.com/dexidp/dex/storage"
"github.com/dexidp/dex/version"
@@ -34,7 +33,7 @@ const (
)
// NewAPI returns a server which implements the gRPC API interface.
func NewAPI(s storage.Storage, logger logrus.FieldLogger) api.DexServer {
func NewAPI(s storage.Storage, logger log.Logger) api.DexServer {
return dexAPI{
s: s,
logger: logger,
@@ -43,7 +42,7 @@ func NewAPI(s storage.Storage, logger logrus.FieldLogger) api.DexServer {
type dexAPI struct {
s storage.Storage
logger logrus.FieldLogger
logger log.Logger
}
func (d dexAPI) CreateClient(ctx context.Context, req *api.CreateClientReq) (*api.CreateClientResp, error) {
+10 -9
View File
@@ -11,6 +11,7 @@ import (
"google.golang.org/grpc"
"github.com/dexidp/dex/api"
"github.com/dexidp/dex/pkg/log"
"github.com/dexidp/dex/server/internal"
"github.com/dexidp/dex/storage"
"github.com/dexidp/dex/storage/memory"
@@ -28,7 +29,7 @@ type apiClient struct {
}
// newAPI constructs a gRCP client connected to a backing server.
func newAPI(s storage.Storage, logger logrus.FieldLogger, t *testing.T) *apiClient {
func newAPI(s storage.Storage, logger log.Logger, t *testing.T) *apiClient {
l, err := net.Listen("tcp", "127.0.0.1:0")
if err != nil {
t.Fatal(err)
@@ -57,11 +58,11 @@ func newAPI(s storage.Storage, logger logrus.FieldLogger, t *testing.T) *apiClie
// Attempts to create, update and delete a test Password
func TestPassword(t *testing.T) {
logger := &logrus.Logger{
logger := log.NewLogrusLogger(&logrus.Logger{
Out: os.Stderr,
Formatter: &logrus.TextFormatter{DisableColors: true},
Level: logrus.DebugLevel,
}
})
s := memory.New(logger)
client := newAPI(s, logger, t)
@@ -122,11 +123,11 @@ func TestPassword(t *testing.T) {
// Ensures checkCost returns expected values
func TestCheckCost(t *testing.T) {
logger := &logrus.Logger{
logger := log.NewLogrusLogger(&logrus.Logger{
Out: os.Stderr,
Formatter: &logrus.TextFormatter{DisableColors: true},
Level: logrus.DebugLevel,
}
})
s := memory.New(logger)
client := newAPI(s, logger, t)
@@ -179,11 +180,11 @@ func TestCheckCost(t *testing.T) {
// Attempts to list and revoke an exisiting refresh token.
func TestRefreshToken(t *testing.T) {
logger := &logrus.Logger{
logger := log.NewLogrusLogger(&logrus.Logger{
Out: os.Stderr,
Formatter: &logrus.TextFormatter{DisableColors: true},
Level: logrus.DebugLevel,
}
})
s := memory.New(logger)
client := newAPI(s, logger, t)
@@ -292,11 +293,11 @@ func TestRefreshToken(t *testing.T) {
}
func TestUpdateClient(t *testing.T) {
logger := &logrus.Logger{
logger := log.NewLogrusLogger(&logrus.Logger{
Out: os.Stderr,
Formatter: &logrus.TextFormatter{DisableColors: true},
Level: logrus.DebugLevel,
}
})
s := memory.New(logger)
client := newAPI(s, logger, t)

Some files were not shown because too many files have changed in this diff Show More