diff --git a/cmd/drone-server/drone.go b/cmd/drone-server/drone.go index 6377e12a..8d1717ef 100644 --- a/cmd/drone-server/drone.go +++ b/cmd/drone-server/drone.go @@ -19,6 +19,7 @@ import ( runner "github.com/drone/drone/pkg/runner/builtin" "github.com/drone/drone/pkg/store" + _ "github.com/drone/drone/pkg/remote/builtin/github" _ "github.com/drone/drone/pkg/store/builtin" _ "net/http/pprof" @@ -49,7 +50,7 @@ func main() { panic(err) } - remote, err := remote.New(settings) + remote, err := remote.New(settings.Remote.Driver, settings) if err != nil { panic(err) } diff --git a/pkg/config/config.go b/pkg/config/config.go index f227add1..f7805a6d 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -1,7 +1,6 @@ package config import ( - "fmt" "io/ioutil" "os" "path" diff --git a/pkg/remote/builtin/github/github.go b/pkg/remote/builtin/github/github.go index 1deec057..796619ce 100644 --- a/pkg/remote/builtin/github/github.go +++ b/pkg/remote/builtin/github/github.go @@ -12,6 +12,7 @@ import ( "github.com/drone/drone/Godeps/_workspace/src/github.com/hashicorp/golang-lru" "github.com/drone/drone/pkg/config" "github.com/drone/drone/pkg/oauth2" + "github.com/drone/drone/pkg/remote" common "github.com/drone/drone/pkg/types" "github.com/drone/drone/pkg/utils/httputil" @@ -19,6 +20,7 @@ import ( ) const ( + DefaultURL = "https://github.com" DefaultScope = "repo,repo:status,user:email" ) @@ -35,7 +37,11 @@ type GitHub struct { cache *lru.Cache } -func New(conf *config.Config) *GitHub { +func init() { + remote.Register("github", NewDriver) +} + +func NewDriver(conf *config.Config) (remote.Remote, error) { var github = GitHub{ API: conf.Github.API, URL: conf.Github.Host, @@ -49,7 +55,7 @@ func New(conf *config.Config) *GitHub { var err error github.cache, err = lru.New(1028) if err != nil { - panic(err) + return nil, err } // the API must have a trailing slash @@ -60,12 +66,12 @@ func New(conf *config.Config) *GitHub { if strings.HasSuffix(github.URL, "/") { github.URL = github.URL[:len(github.URL)-1] } - return &github + return &github, nil } func (g *GitHub) Login(token, secret string) (*common.User, error) { client := NewClient(g.API, token, g.SkipVerify) - login, err := GetUserEmail(client, g.URL) + login, err := GetUserEmail(client) if err != nil { return nil, err } diff --git a/pkg/remote/builtin/github/helper.go b/pkg/remote/builtin/github/helper.go index f54c19d6..bedd39ce 100644 --- a/pkg/remote/builtin/github/helper.go +++ b/pkg/remote/builtin/github/helper.go @@ -37,7 +37,7 @@ func NewClient(uri, token string, skipVerify bool) *github.Client { // GetUserEmail is a heper function that retrieves the currently // authenticated user from GitHub + Email address. -func GetUserEmail(client *github.Client, defaultURL string) (*github.User, error) { +func GetUserEmail(client *github.Client) (*github.User, error) { user, _, err := client.Users.Get("") if err != nil { return nil, err @@ -58,7 +58,7 @@ func GetUserEmail(client *github.Client, defaultURL string) (*github.User, error // WARNING, HACK // for out-of-date github enterprise editions the primary // and verified fields won't exist. - if !strings.HasPrefix(*user.HTMLURL, defaultURL) && len(emails) != 0 { + if !strings.HasPrefix(*user.HTMLURL, DefaultURL) && len(emails) != 0 { user.Email = emails[0].Email return user, nil } diff --git a/pkg/remote/remote.go b/pkg/remote/remote.go index fe4486ae..0da71981 100644 --- a/pkg/remote/remote.go +++ b/pkg/remote/remote.go @@ -1,17 +1,42 @@ package remote import ( - "errors" "fmt" "net/http" - "strings" "github.com/drone/drone/pkg/config" "github.com/drone/drone/pkg/oauth2" - "github.com/drone/drone/pkg/remote/builtin/github" common "github.com/drone/drone/pkg/types" ) +var drivers = make(map[string]DriverFunc) + +// Register makes a remote driver available by the provided name. +// If Register is called twice with the same name or if driver is nil, +// it panics. +func Register(name string, driver DriverFunc) { + if driver == nil { + panic("remote: Register driver is nil") + } + if _, dup := drivers[name]; dup { + panic("remote: Register called twice for driver " + name) + } + drivers[name] = driver +} + +// DriverFunc returns a new connection to the remote. +// Config is a struct, with base remote configuration. +type DriverFunc func(conf *config.Config) (Remote, error) + +// New creates a new remote connection. +func New(driver string, conf *config.Config) (Remote, error) { + fn, ok := drivers[driver] + if !ok { + return nil, fmt.Errorf("remote: unknown driver %q", driver) + } + return fn(conf) +} + type Remote interface { // Login authenticates the session and returns the // remote user details. @@ -64,14 +89,3 @@ type Remote interface { // Default scope for remote Scope() string } - -func New(conf *config.Config) (Remote, error) { - switch strings.ToLower(conf.Remote.Driver) { - case "github": - return github.New(conf), nil - case "": - return nil, errors.New("Remote not specifed, please set env variable DRONE_REMOTE_DRIVER") - default: - return nil, errors.New(fmt.Sprintf("Remote driver not supported: DRONE_REMOTE_DRIVER=%s", conf.Remote.Driver)) - } -}