cmd/dex: add logging config and serve logger for different modules.

This commit is contained in:
rithu john 2016-11-22 15:35:46 -08:00
parent 79c51f2983
commit 2e22a948cf
20 changed files with 191 additions and 43 deletions

View file

@ -8,6 +8,7 @@ import (
"golang.org/x/crypto/bcrypt" "golang.org/x/crypto/bcrypt"
"github.com/Sirupsen/logrus"
"github.com/coreos/dex/connector" "github.com/coreos/dex/connector"
"github.com/coreos/dex/connector/github" "github.com/coreos/dex/connector/github"
"github.com/coreos/dex/connector/ldap" "github.com/coreos/dex/connector/ldap"
@ -29,6 +30,7 @@ type Config struct {
OAuth2 OAuth2 `json:"oauth2"` OAuth2 OAuth2 `json:"oauth2"`
GRPC GRPC `json:"grpc"` GRPC GRPC `json:"grpc"`
Expiry Expiry `json:"expiry"` Expiry Expiry `json:"expiry"`
Logger Logger `json:"logger"`
Frontend server.WebConfig `json:"frontend"` Frontend server.WebConfig `json:"frontend"`
@ -119,7 +121,7 @@ type Storage struct {
// StorageConfig is a configuration that can create a storage. // StorageConfig is a configuration that can create a storage.
type StorageConfig interface { type StorageConfig interface {
Open() (storage.Storage, error) Open(logrus.FieldLogger) (storage.Storage, error)
} }
var storages = map[string]func() StorageConfig{ var storages = map[string]func() StorageConfig{
@ -170,7 +172,7 @@ type Connector struct {
// ConnectorConfig is a configuration that can open a connector. // ConnectorConfig is a configuration that can open a connector.
type ConnectorConfig interface { type ConnectorConfig interface {
Open() (connector.Connector, error) Open(logrus.FieldLogger) (connector.Connector, error)
} }
var connectors = map[string]func() ConnectorConfig{ var connectors = map[string]func() ConnectorConfig{
@ -223,3 +225,12 @@ type Expiry struct {
// IdTokens defines the duration of time for which the IdTokens will be valid. // IdTokens defines the duration of time for which the IdTokens will be valid.
IDTokens string `json:"idTokens"` IDTokens string `json:"idTokens"`
} }
// Logger holds configuration required to customize logging for dex.
type Logger struct {
// Level sets logging level severity.
Level string `json:"level"`
// Format specifies the format to be used for logging.
Format string `json:"format"`
}

View file

@ -59,6 +59,10 @@ staticPasswords:
expiry: expiry:
signingKeys: "6h" signingKeys: "6h"
idTokens: "24h" idTokens: "24h"
logger:
level: "debug"
format: "json"
`) `)
want := Config{ want := Config{
@ -120,6 +124,10 @@ expiry:
SigningKeys: "6h", SigningKeys: "6h",
IDTokens: "24h", IDTokens: "24h",
}, },
Logger: Logger{
Level: "debug",
Format: "json",
},
} }
var c Config var c Config

View file

@ -9,8 +9,11 @@ import (
"log" "log"
"net" "net"
"net/http" "net/http"
"os"
"strings"
"time" "time"
"github.com/Sirupsen/logrus"
"github.com/ghodss/yaml" "github.com/ghodss/yaml"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"golang.org/x/net/context" "golang.org/x/net/context"
@ -111,6 +114,8 @@ func serve(cmd *cobra.Command, args []string) error {
} }
} }
logger, _ := newLogger(c.Logger.Level, c.Logger.Format)
connectors := make([]server.Connector, len(c.Connectors)) connectors := make([]server.Connector, len(c.Connectors))
for i, conn := range c.Connectors { for i, conn := range c.Connectors {
if conn.ID == "" { if conn.ID == "" {
@ -119,7 +124,8 @@ func serve(cmd *cobra.Command, args []string) error {
if conn.Config == nil { if conn.Config == nil {
return fmt.Errorf("no config field for connector %q", conn.ID) return fmt.Errorf("no config field for connector %q", conn.ID)
} }
c, err := conn.Config.Open() connectorLogger := logger.WithField("connector", conn.Name)
c, err := conn.Config.Open(connectorLogger)
if err != nil { if err != nil {
return fmt.Errorf("open %s: %v", conn.ID, err) return fmt.Errorf("open %s: %v", conn.ID, err)
} }
@ -130,7 +136,7 @@ func serve(cmd *cobra.Command, args []string) error {
} }
} }
s, err := c.Storage.Config.Open() s, err := c.Storage.Config.Open(logger)
if err != nil { if err != nil {
return fmt.Errorf("initializing storage: %v", err) return fmt.Errorf("initializing storage: %v", err)
} }
@ -153,6 +159,7 @@ func serve(cmd *cobra.Command, args []string) error {
Storage: s, Storage: s,
Web: c.Frontend, Web: c.Frontend,
EnablePasswordDB: c.EnablePasswordDB, EnablePasswordDB: c.EnablePasswordDB,
Logger: logger,
} }
if c.Expiry.SigningKeys != "" { if c.Expiry.SigningKeys != "" {
signingKeys, err := time.ParseDuration(c.Expiry.SigningKeys) signingKeys, err := time.ParseDuration(c.Expiry.SigningKeys)
@ -203,3 +210,33 @@ func serve(cmd *cobra.Command, args []string) error {
return <-errc return <-errc
} }
func newLogger(level string, format string) (logrus.FieldLogger, error) {
var logLevel logrus.Level
switch strings.ToLower(level) {
case "debug":
logLevel = logrus.DebugLevel
case "", "info":
logLevel = logrus.InfoLevel
case "error":
logLevel = logrus.ErrorLevel
default:
return nil, fmt.Errorf("unsupported logLevel: %s", level)
}
var formatter logrus.Formatter
switch strings.ToLower(format) {
case "", "text":
formatter = &logrus.TextFormatter{DisableColors: true}
case "json":
formatter = &logrus.JSONFormatter{}
default:
return nil, fmt.Errorf("unsupported logger format: %s", format)
}
return &logrus.Logger{
Out: os.Stderr,
Formatter: formatter,
Level: logLevel,
}, nil
}

View file

@ -13,6 +13,7 @@ import (
"golang.org/x/oauth2" "golang.org/x/oauth2"
"golang.org/x/oauth2/github" "golang.org/x/oauth2/github"
"github.com/Sirupsen/logrus"
"github.com/coreos/dex/connector" "github.com/coreos/dex/connector"
) )
@ -31,12 +32,13 @@ type Config struct {
} }
// Open returns a strategy for logging in through GitHub. // Open returns a strategy for logging in through GitHub.
func (c *Config) Open() (connector.Connector, error) { func (c *Config) Open(logger logrus.FieldLogger) (connector.Connector, error) {
return &githubConnector{ return &githubConnector{
redirectURI: c.RedirectURI, redirectURI: c.RedirectURI,
org: c.Org, org: c.Org,
clientID: c.ClientID, clientID: c.ClientID,
clientSecret: c.ClientSecret, clientSecret: c.ClientSecret,
logger: logger,
}, nil }, nil
} }
@ -55,6 +57,7 @@ type githubConnector struct {
org string org string
clientID string clientID string
clientSecret string clientSecret string
logger logrus.FieldLogger
} }
func (c *githubConnector) oauth2Config(scopes connector.Scopes) *oauth2.Config { func (c *githubConnector) oauth2Config(scopes connector.Scopes) *oauth2.Config {

View file

@ -13,6 +13,7 @@ import (
"golang.org/x/net/context" "golang.org/x/net/context"
"gopkg.in/ldap.v2" "gopkg.in/ldap.v2"
"github.com/Sirupsen/logrus"
"github.com/coreos/dex/connector" "github.com/coreos/dex/connector"
) )
@ -135,8 +136,8 @@ func parseScope(s string) (int, bool) {
} }
// Open returns an authentication strategy using LDAP. // Open returns an authentication strategy using LDAP.
func (c *Config) Open() (connector.Connector, error) { func (c *Config) Open(logger logrus.FieldLogger) (connector.Connector, error) {
conn, err := c.OpenConnector() conn, err := c.OpenConnector(logger)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -149,7 +150,7 @@ type refreshData struct {
} }
// OpenConnector is the same as Open but returns a type with all implemented connector interfaces. // OpenConnector is the same as Open but returns a type with all implemented connector interfaces.
func (c *Config) OpenConnector() (interface { func (c *Config) OpenConnector(logger logrus.FieldLogger) (interface {
connector.Connector connector.Connector
connector.PasswordConnector connector.PasswordConnector
connector.RefreshConnector connector.RefreshConnector
@ -206,7 +207,7 @@ func (c *Config) OpenConnector() (interface {
if !ok { if !ok {
return nil, fmt.Errorf("userSearch.Scope unknown value %q", c.GroupSearch.Scope) return nil, fmt.Errorf("userSearch.Scope unknown value %q", c.GroupSearch.Scope)
} }
return &ldapConnector{*c, userSearchScope, groupSearchScope, tlsConfig}, nil return &ldapConnector{*c, userSearchScope, groupSearchScope, tlsConfig, logger}, nil
} }
type ldapConnector struct { type ldapConnector struct {
@ -216,6 +217,8 @@ type ldapConnector struct {
groupSearchScope int groupSearchScope int
tlsConfig *tls.Config tlsConfig *tls.Config
logger logrus.FieldLogger
} }
var ( var (

View file

@ -9,12 +9,13 @@ import (
"golang.org/x/net/context" "golang.org/x/net/context"
"github.com/Sirupsen/logrus"
"github.com/coreos/dex/connector" "github.com/coreos/dex/connector"
) )
// NewCallbackConnector returns a mock connector which requires no user interaction. It always returns // NewCallbackConnector returns a mock connector which requires no user interaction. It always returns
// the same (fake) identity. // the same (fake) identity.
func NewCallbackConnector() connector.Connector { func NewCallbackConnector(logger logrus.FieldLogger) connector.Connector {
return &Callback{ return &Callback{
Identity: connector.Identity{ Identity: connector.Identity{
UserID: "0-385-28089-0", UserID: "0-385-28089-0",
@ -24,6 +25,7 @@ func NewCallbackConnector() connector.Connector {
Groups: []string{"authors"}, Groups: []string{"authors"},
ConnectorData: connectorData, ConnectorData: connectorData,
}, },
Logger: logger,
} }
} }
@ -37,6 +39,7 @@ var (
type Callback struct { type Callback struct {
// The returned identity. // The returned identity.
Identity connector.Identity Identity connector.Identity
Logger logrus.FieldLogger
} }
// LoginURL returns the URL to redirect the user to login with. // LoginURL returns the URL to redirect the user to login with.
@ -67,8 +70,8 @@ func (m *Callback) Refresh(ctx context.Context, s connector.Scopes, identity con
type CallbackConfig struct{} type CallbackConfig struct{}
// Open returns an authentication strategy which requires no user interaction. // Open returns an authentication strategy which requires no user interaction.
func (c *CallbackConfig) Open() (connector.Connector, error) { func (c *CallbackConfig) Open(logger logrus.FieldLogger) (connector.Connector, error) {
return NewCallbackConnector(), nil return NewCallbackConnector(logger), nil
} }
// PasswordConfig holds the configuration for a mock connector which prompts for the supplied // PasswordConfig holds the configuration for a mock connector which prompts for the supplied
@ -79,19 +82,20 @@ type PasswordConfig struct {
} }
// Open returns an authentication strategy which prompts for a predefined username and password. // Open returns an authentication strategy which prompts for a predefined username and password.
func (c *PasswordConfig) Open() (connector.Connector, error) { func (c *PasswordConfig) Open(logger logrus.FieldLogger) (connector.Connector, error) {
if c.Username == "" { if c.Username == "" {
return nil, errors.New("no username supplied") return nil, errors.New("no username supplied")
} }
if c.Password == "" { if c.Password == "" {
return nil, errors.New("no password supplied") return nil, errors.New("no password supplied")
} }
return &passwordConnector{c.Username, c.Password}, nil return &passwordConnector{c.Username, c.Password, logger}, nil
} }
type passwordConnector struct { type passwordConnector struct {
username string username string
password string password string
logger logrus.FieldLogger
} }
func (p passwordConnector) Close() error { return nil } func (p passwordConnector) Close() error { return nil }

View file

@ -6,6 +6,7 @@ import (
"fmt" "fmt"
"net/http" "net/http"
"github.com/Sirupsen/logrus"
"github.com/coreos/go-oidc" "github.com/coreos/go-oidc"
"golang.org/x/net/context" "golang.org/x/net/context"
"golang.org/x/oauth2" "golang.org/x/oauth2"
@ -25,7 +26,7 @@ type Config struct {
// Open returns a connector which can be used to login users through an upstream // Open returns a connector which can be used to login users through an upstream
// OpenID Connect provider. // OpenID Connect provider.
func (c *Config) Open() (conn connector.Connector, err error) { func (c *Config) Open(logger logrus.FieldLogger) (conn connector.Connector, err error) {
ctx, cancel := context.WithCancel(context.Background()) ctx, cancel := context.WithCancel(context.Background())
provider, err := oidc.NewProvider(ctx, c.Issuer) provider, err := oidc.NewProvider(ctx, c.Issuer)
@ -55,6 +56,7 @@ func (c *Config) Open() (conn connector.Connector, err error) {
oidc.VerifyExpiry(), oidc.VerifyExpiry(),
oidc.VerifyAudience(clientID), oidc.VerifyAudience(clientID),
), ),
logger: logger,
}, nil }, nil
} }
@ -68,6 +70,7 @@ type oidcConnector struct {
verifier *oidc.IDTokenVerifier verifier *oidc.IDTokenVerifier
ctx context.Context ctx context.Context
cancel context.CancelFunc cancel context.CancelFunc
logger logrus.FieldLogger
} }
func (c *oidcConnector) Close() error { func (c *oidcConnector) Close() error {

View file

@ -2,15 +2,23 @@ package server
import ( import (
"context" "context"
"os"
"testing" "testing"
"github.com/Sirupsen/logrus"
"github.com/coreos/dex/api" "github.com/coreos/dex/api"
"github.com/coreos/dex/storage/memory" "github.com/coreos/dex/storage/memory"
) )
// Attempts to create, update and delete a test Password // Attempts to create, update and delete a test Password
func TestPassword(t *testing.T) { func TestPassword(t *testing.T) {
s := memory.New() logger := &logrus.Logger{
Out: os.Stderr,
Formatter: &logrus.TextFormatter{DisableColors: true},
Level: logrus.DebugLevel,
}
s := memory.New(logger)
serv := NewAPI(s) serv := NewAPI(s)
ctx := context.Background() ctx := context.Background()

View file

@ -13,6 +13,7 @@ import (
"golang.org/x/crypto/bcrypt" "golang.org/x/crypto/bcrypt"
"golang.org/x/net/context" "golang.org/x/net/context"
"github.com/Sirupsen/logrus"
"github.com/gorilla/mux" "github.com/gorilla/mux"
"github.com/coreos/dex/connector" "github.com/coreos/dex/connector"
@ -57,6 +58,8 @@ type Config struct {
EnablePasswordDB bool EnablePasswordDB bool
Web WebConfig Web WebConfig
Logger logrus.FieldLogger
} }
// WebConfig holds the server's frontend templates and asset configuration. // WebConfig holds the server's frontend templates and asset configuration.
@ -112,6 +115,8 @@ type Server struct {
now func() time.Time now func() time.Time
idTokensValidFor time.Duration idTokensValidFor time.Duration
logger logrus.FieldLogger
} }
// NewServer constructs a server from the provided config. // NewServer constructs a server from the provided config.
@ -182,6 +187,7 @@ func newServer(ctx context.Context, c Config, rotationStrategy rotationStrategy)
skipApproval: c.SkipApprovalScreen, skipApproval: c.SkipApprovalScreen,
now: now, now: now,
templates: tmpls, templates: tmpls,
logger: c.Logger,
} }
for _, conn := range c.Connectors { for _, conn := range c.Connectors {

View file

@ -20,6 +20,7 @@ import (
"testing" "testing"
"time" "time"
"github.com/Sirupsen/logrus"
oidc "github.com/coreos/go-oidc" oidc "github.com/coreos/go-oidc"
"github.com/kylelemons/godebug/pretty" "github.com/kylelemons/godebug/pretty"
"golang.org/x/crypto/bcrypt" "golang.org/x/crypto/bcrypt"
@ -72,19 +73,26 @@ FDWV28nTP9sqbtsmU8Tem2jzMvZ7C/Q0AuDoKELFUpux8shm8wfIhyaPnXUGZoAZ
Np4vUwMSYV5mopESLWOg3loBxKyLGFtgGKVCjGiQvy6zISQ4fQo= Np4vUwMSYV5mopESLWOg3loBxKyLGFtgGKVCjGiQvy6zISQ4fQo=
-----END RSA PRIVATE KEY-----`) -----END RSA PRIVATE KEY-----`)
var logger = &logrus.Logger{
Out: os.Stderr,
Formatter: &logrus.TextFormatter{DisableColors: true},
Level: logrus.DebugLevel,
}
func newTestServer(ctx context.Context, t *testing.T, updateConfig func(c *Config)) (*httptest.Server, *Server) { func newTestServer(ctx context.Context, t *testing.T, updateConfig func(c *Config)) (*httptest.Server, *Server) {
var server *Server var server *Server
s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
server.ServeHTTP(w, r) server.ServeHTTP(w, r)
})) }))
config := Config{ config := Config{
Issuer: s.URL, Issuer: s.URL,
Storage: memory.New(), Storage: memory.New(logger),
Connectors: []Connector{ Connectors: []Connector{
{ {
ID: "mock", ID: "mock",
DisplayName: "Mock", DisplayName: "Mock",
Connector: mock.NewCallbackConnector(), Connector: mock.NewCallbackConnector(logger),
}, },
}, },
Web: WebConfig{ Web: WebConfig{
@ -367,12 +375,17 @@ func TestOAuth2CodeFlow(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background()) ctx, cancel := context.WithCancel(context.Background())
defer cancel() defer cancel()
logger := &logrus.Logger{
Out: os.Stderr,
Formatter: &logrus.TextFormatter{DisableColors: true},
Level: logrus.DebugLevel,
}
httpServer, s := newTestServer(ctx, t, func(c *Config) { httpServer, s := newTestServer(ctx, t, func(c *Config) {
c.Issuer = c.Issuer + "/non-root-path" c.Issuer = c.Issuer + "/non-root-path"
c.Now = now c.Now = now
c.IDTokensValidFor = idTokensValidFor c.IDTokensValidFor = idTokensValidFor
// Create a new mock callback connector for each test case. // Create a new mock callback connector for each test case.
conn = mock.NewCallbackConnector().(*mock.Callback) conn = mock.NewCallbackConnector(logger).(*mock.Callback)
c.Connectors = []Connector{ c.Connectors = []Connector{
{ {
ID: "mock", ID: "mock",
@ -743,7 +756,7 @@ func TestCrossClientScopes(t *testing.T) {
} }
func TestPasswordDB(t *testing.T) { func TestPasswordDB(t *testing.T) {
s := memory.New() s := memory.New(logger)
conn := newPasswordDB(s) conn := newPasswordDB(s)
pw := "hi" pw := "hi"
@ -840,7 +853,7 @@ func TestKeyCacher(t *testing.T) {
tNow := time.Now() tNow := time.Now()
now := func() time.Time { return tNow } now := func() time.Time { return tNow }
s := memory.New() s := memory.New(logger)
tests := []struct { tests := []struct {
before func() before func()

View file

@ -21,6 +21,7 @@ import (
"strings" "strings"
"time" "time"
"github.com/Sirupsen/logrus"
"github.com/ghodss/yaml" "github.com/ghodss/yaml"
"github.com/gtank/cryptopasta" "github.com/gtank/cryptopasta"
"golang.org/x/net/context" "golang.org/x/net/context"
@ -33,6 +34,7 @@ type client struct {
client *http.Client client *http.Client
baseURL string baseURL string
namespace string namespace string
logger logrus.FieldLogger
// Hash function to map IDs (which could span a large range) to Kubernetes names. // Hash function to map IDs (which could span a large range) to Kubernetes names.
// While this is not currently upgradable, it could be in the future. // While this is not currently upgradable, it could be in the future.
@ -230,7 +232,7 @@ func (c *client) put(resource, name string, v interface{}) error {
return checkHTTPErr(resp, http.StatusOK) return checkHTTPErr(resp, http.StatusOK)
} }
func newClient(cluster k8sapi.Cluster, user k8sapi.AuthInfo, namespace string) (*client, error) { func newClient(cluster k8sapi.Cluster, user k8sapi.AuthInfo, namespace string, logger logrus.FieldLogger) (*client, error) {
tlsConfig := cryptopasta.DefaultTLSConfig() tlsConfig := cryptopasta.DefaultTLSConfig()
data := func(b string, file string) ([]byte, error) { data := func(b string, file string) ([]byte, error) {
if b != "" { if b != "" {
@ -303,6 +305,7 @@ func newClient(cluster k8sapi.Cluster, user k8sapi.AuthInfo, namespace string) (
hash: func() hash.Hash { return fnv.New64() }, hash: func() hash.Hash { return fnv.New64() },
namespace: namespace, namespace: namespace,
apiVersion: "oidc.coreos.com/v1", apiVersion: "oidc.coreos.com/v1",
logger: logger,
}, nil }, nil
} }

View file

@ -10,6 +10,7 @@ import (
"golang.org/x/net/context" "golang.org/x/net/context"
"github.com/Sirupsen/logrus"
"github.com/coreos/dex/storage" "github.com/coreos/dex/storage"
"github.com/coreos/dex/storage/kubernetes/k8sapi" "github.com/coreos/dex/storage/kubernetes/k8sapi"
) )
@ -39,8 +40,8 @@ type Config struct {
} }
// Open returns a storage using Kubernetes third party resource. // Open returns a storage using Kubernetes third party resource.
func (c *Config) Open() (storage.Storage, error) { func (c *Config) Open(logger logrus.FieldLogger) (storage.Storage, error) {
cli, err := c.open() cli, err := c.open(logger)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -48,7 +49,7 @@ func (c *Config) Open() (storage.Storage, error) {
} }
// open returns a client with no garbage collection. // open returns a client with no garbage collection.
func (c *Config) open() (*client, error) { func (c *Config) open(logger logrus.FieldLogger) (*client, error) {
if c.InCluster && (c.KubeConfigFile != "") { if c.InCluster && (c.KubeConfigFile != "") {
return nil, errors.New("cannot specify both 'inCluster' and 'kubeConfigFile'") return nil, errors.New("cannot specify both 'inCluster' and 'kubeConfigFile'")
} }
@ -71,7 +72,7 @@ func (c *Config) open() (*client, error) {
return nil, err return nil, err
} }
cli, err := newClient(cluster, user, namespace) cli, err := newClient(cluster, user, namespace, logger)
if err != nil { if err != nil {
return nil, fmt.Errorf("create client: %v", err) return nil, fmt.Errorf("create client: %v", err)
} }

View file

@ -5,6 +5,7 @@ import (
"os" "os"
"testing" "testing"
"github.com/Sirupsen/logrus"
"github.com/coreos/dex/storage" "github.com/coreos/dex/storage"
"github.com/coreos/dex/storage/conformance" "github.com/coreos/dex/storage/conformance"
) )
@ -22,7 +23,12 @@ func loadClient(t *testing.T) *client {
if config.KubeConfigFile == "" { if config.KubeConfigFile == "" {
t.Skipf("test environment variable %q not set, skipping", testKubeConfigEnv) t.Skipf("test environment variable %q not set, skipping", testKubeConfigEnv)
} }
s, err := config.open() logger := &logrus.Logger{
Out: os.Stderr,
Formatter: &logrus.TextFormatter{DisableColors: true},
Level: logrus.DebugLevel,
}
s, err := config.open(logger)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }

View file

@ -6,17 +6,19 @@ import (
"sync" "sync"
"time" "time"
"github.com/Sirupsen/logrus"
"github.com/coreos/dex/storage" "github.com/coreos/dex/storage"
) )
// New returns an in memory storage. // New returns an in memory storage.
func New() storage.Storage { func New(logger logrus.FieldLogger) storage.Storage {
return &memStorage{ return &memStorage{
clients: make(map[string]storage.Client), clients: make(map[string]storage.Client),
authCodes: make(map[string]storage.AuthCode), authCodes: make(map[string]storage.AuthCode),
refreshTokens: make(map[string]storage.RefreshToken), refreshTokens: make(map[string]storage.RefreshToken),
authReqs: make(map[string]storage.AuthRequest), authReqs: make(map[string]storage.AuthRequest),
passwords: make(map[string]storage.Password), passwords: make(map[string]storage.Password),
logger: logger,
} }
} }
@ -28,8 +30,8 @@ type Config struct {
} }
// Open always returns a new in memory storage. // Open always returns a new in memory storage.
func (c *Config) Open() (storage.Storage, error) { func (c *Config) Open(logger logrus.FieldLogger) (storage.Storage, error) {
return New(), nil return New(logger), nil
} }
type memStorage struct { type memStorage struct {
@ -42,6 +44,8 @@ type memStorage struct {
passwords map[string]storage.Password passwords map[string]storage.Password
keys storage.Keys keys storage.Keys
logger logrus.FieldLogger
} }
func (s *memStorage) tx(f func()) { func (s *memStorage) tx(f func()) {

View file

@ -1,11 +1,23 @@
package memory package memory
import ( import (
"os"
"testing" "testing"
"github.com/Sirupsen/logrus"
"github.com/coreos/dex/storage"
"github.com/coreos/dex/storage/conformance" "github.com/coreos/dex/storage/conformance"
) )
func TestStorage(t *testing.T) { func TestStorage(t *testing.T) {
conformance.RunTests(t, New) logger := &logrus.Logger{
Out: os.Stderr,
Formatter: &logrus.TextFormatter{DisableColors: true},
Level: logrus.DebugLevel,
}
newStorage := func() storage.Storage {
return New(logger)
}
conformance.RunTests(t, newStorage)
} }

View file

@ -1,14 +1,21 @@
package memory package memory
import ( import (
"os"
"reflect" "reflect"
"testing" "testing"
"github.com/Sirupsen/logrus"
"github.com/coreos/dex/storage" "github.com/coreos/dex/storage"
) )
func TestStaticClients(t *testing.T) { func TestStaticClients(t *testing.T) {
s := New() logger := &logrus.Logger{
Out: os.Stderr,
Formatter: &logrus.TextFormatter{DisableColors: true},
Level: logrus.DebugLevel,
}
s := New(logger)
c1 := storage.Client{ID: "foo", Secret: "foo_secret"} c1 := storage.Client{ID: "foo", Secret: "foo_secret"}
c2 := storage.Client{ID: "bar", Secret: "bar_secret"} c2 := storage.Client{ID: "bar", Secret: "bar_secret"}

View file

@ -6,6 +6,7 @@ import (
"net/url" "net/url"
"strconv" "strconv"
"github.com/Sirupsen/logrus"
"github.com/coreos/dex/storage" "github.com/coreos/dex/storage"
) )
@ -16,15 +17,15 @@ type SQLite3 struct {
} }
// Open creates a new storage implementation backed by SQLite3 // Open creates a new storage implementation backed by SQLite3
func (s *SQLite3) Open() (storage.Storage, error) { func (s *SQLite3) Open(logger logrus.FieldLogger) (storage.Storage, error) {
conn, err := s.open() conn, err := s.open(logger)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return conn, nil return conn, nil
} }
func (s *SQLite3) open() (*conn, error) { func (s *SQLite3) open(logger logrus.FieldLogger) (*conn, error) {
db, err := sql.Open("sqlite3", s.File) db, err := sql.Open("sqlite3", s.File)
if err != nil { if err != nil {
return nil, err return nil, err
@ -34,7 +35,7 @@ func (s *SQLite3) open() (*conn, error) {
// doesn't support this, so limit the number of connections to 1. // doesn't support this, so limit the number of connections to 1.
db.SetMaxOpenConns(1) db.SetMaxOpenConns(1)
} }
c := &conn{db, flavorSQLite3} c := &conn{db, flavorSQLite3, logger}
if _, err := c.migrate(); err != nil { if _, err := c.migrate(); err != nil {
return nil, fmt.Errorf("failed to perform migrations: %v", err) return nil, fmt.Errorf("failed to perform migrations: %v", err)
} }
@ -70,15 +71,15 @@ type Postgres struct {
} }
// Open creates a new storage implementation backed by Postgres. // Open creates a new storage implementation backed by Postgres.
func (p *Postgres) Open() (storage.Storage, error) { func (p *Postgres) Open(logger logrus.FieldLogger) (storage.Storage, error) {
conn, err := p.open() conn, err := p.open(logger)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return conn, nil return conn, nil
} }
func (p *Postgres) open() (*conn, error) { func (p *Postgres) open(logger logrus.FieldLogger) (*conn, error) {
v := url.Values{} v := url.Values{}
set := func(key, val string) { set := func(key, val string) {
if val != "" { if val != "" {
@ -113,7 +114,7 @@ func (p *Postgres) open() (*conn, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
c := &conn{db, flavorPostgres} c := &conn{db, flavorPostgres, logger}
if _, err := c.migrate(); err != nil { if _, err := c.migrate(); err != nil {
return nil, fmt.Errorf("failed to perform migrations: %v", err) return nil, fmt.Errorf("failed to perform migrations: %v", err)
} }

View file

@ -7,6 +7,7 @@ import (
"testing" "testing"
"time" "time"
"github.com/Sirupsen/logrus"
"github.com/coreos/dex/storage" "github.com/coreos/dex/storage"
"github.com/coreos/dex/storage/conformance" "github.com/coreos/dex/storage/conformance"
) )
@ -41,13 +42,19 @@ func cleanDB(c *conn) error {
return err return err
} }
var logger = &logrus.Logger{
Out: os.Stderr,
Formatter: &logrus.TextFormatter{DisableColors: true},
Level: logrus.DebugLevel,
}
func TestSQLite3(t *testing.T) { func TestSQLite3(t *testing.T) {
newStorage := func() storage.Storage { newStorage := func() storage.Storage {
// NOTE(ericchiang): In memory means we only get one connection at a time. If we // NOTE(ericchiang): In memory means we only get one connection at a time. If we
// ever write tests that require using multiple connections, for instance to test // ever write tests that require using multiple connections, for instance to test
// transactions, we need to move to a file based system. // transactions, we need to move to a file based system.
s := &SQLite3{":memory:"} s := &SQLite3{":memory:"}
conn, err := s.open() conn, err := s.open(logger)
if err != nil { if err != nil {
fmt.Fprintln(os.Stdout, err) fmt.Fprintln(os.Stdout, err)
t.Fatal(err) t.Fatal(err)
@ -92,7 +99,7 @@ func TestPostgres(t *testing.T) {
} }
newStorage := func() storage.Storage { newStorage := func() storage.Storage {
conn, err := p.open() conn, err := p.open(logger)
if err != nil { if err != nil {
fatal(err) fatal(err)
} }

View file

@ -2,7 +2,10 @@ package sql
import ( import (
"database/sql" "database/sql"
"os"
"testing" "testing"
"github.com/Sirupsen/logrus"
) )
func TestMigrate(t *testing.T) { func TestMigrate(t *testing.T) {
@ -12,7 +15,13 @@ func TestMigrate(t *testing.T) {
} }
defer db.Close() defer db.Close()
c := &conn{db, flavorSQLite3} logger := &logrus.Logger{
Out: os.Stderr,
Formatter: &logrus.TextFormatter{DisableColors: true},
Level: logrus.DebugLevel,
}
c := &conn{db, flavorSQLite3, logger}
for _, want := range []int{len(migrations), 0} { for _, want := range []int{len(migrations), 0} {
got, err := c.migrate() got, err := c.migrate()
if err != nil { if err != nil {

View file

@ -5,6 +5,7 @@ import (
"database/sql" "database/sql"
"regexp" "regexp"
"github.com/Sirupsen/logrus"
"github.com/cockroachdb/cockroach-go/crdb" "github.com/cockroachdb/cockroach-go/crdb"
// import third party drivers // import third party drivers
@ -110,6 +111,7 @@ func (f flavor) translate(query string) string {
type conn struct { type conn struct {
db *sql.DB db *sql.DB
flavor flavor flavor flavor
logger logrus.FieldLogger
} }
func (c *conn) Close() error { func (c *conn) Close() error {