Get Config Data via ConfigManager

This commit is contained in:
Brad Rydzewski 2014-06-12 17:17:59 -07:00
parent f0a8e91a68
commit d64bcdb51d
12 changed files with 229 additions and 282 deletions

View file

@ -51,4 +51,4 @@ dpkg:
-dpkg-deb --build debian/drone -dpkg-deb --build debian/drone
run: run:
@cd server && go run main.go conf.gomake @cd server && go run main.go amber.go

View file

@ -1,86 +0,0 @@
package main
import (
"fmt"
"io/ioutil"
"os"
"os/user"
"path/filepath"
"github.com/BurntSushi/toml"
)
// initialize the .drone directory and create a skeleton config
// file if one does not already exist.
func init() {
// load the current user
u, err := user.Current()
if err != nil {
panic(err)
}
// create the .drone home directory
os.MkdirAll(filepath.Join(u.HomeDir, ".drone"), 0777)
// check for the config file
filename := filepath.Join(u.HomeDir, ".drone", "config.toml")
if _, err := os.Stat(filename); err != nil {
// if not exists, create
ioutil.WriteFile(filename, []byte(defaultConfig), 0777)
}
// load the configuration file and parse
if _, err := toml.DecodeFile(filename, &conf); err != nil {
fmt.Println(err)
os.Exit(1)
return
}
}
var defaultConfig = `
# Enables user self-registration. If false, the system administrator
# will need to manually add users to the system.
registration = true
[smtp]
host = ""
port = ""
from = ""
username = ""
password = ""
[bitbucket]
url = "https://bitbucket.org"
api = "https://bitbucket.org"
client = ""
secret = ""
enabled = false
[github]
url = "https://github.com"
api = "https://api.github.com"
client = ""
secret = ""
enabled = false
[githubenterprise]
url = ""
api = ""
client = ""
secret = ""
enabled = false
[gitlab]
url = ""
api = ""
client = ""
secret = ""
enabled = false
[stash]
url = ""
api = ""
client = ""
secret = ""
enabled = false
`

35
server/database/config.go Normal file
View file

@ -0,0 +1,35 @@
package database
import (
"github.com/BurntSushi/toml"
"github.com/drone/drone/shared/model"
)
type ConfigManager interface {
Find() *model.Config
}
// configManager manages configuration data from a
// configuration file using .toml format
type configManager struct {
conf *model.Config
}
// NewConfigManager initiales a new CommitManager intended to
// manage and persist commits.
func NewConfigManager(filename string) ConfigManager {
c := configManager{}
c.conf = &model.Config{}
// load the configuration file and parse
_, err := toml.DecodeFile(filename, c.conf)
if err != nil {
panic(err)
}
return &c
}
func (c *configManager) Find() *model.Config {
return c.conf
}

View file

@ -4,17 +4,17 @@ import (
"encoding/json" "encoding/json"
"net/http" "net/http"
"github.com/drone/drone/server/resource/config" "github.com/drone/drone/server/database"
"github.com/drone/drone/server/session" "github.com/drone/drone/server/session"
"github.com/gorilla/pat" "github.com/gorilla/pat"
) )
type ConfigHandler struct { type ConfigHandler struct {
conf config.Config conf database.ConfigManager
sess session.Session sess session.Session
} }
func NewConfigHandler(conf config.Config, sess session.Session) *ConfigHandler { func NewConfigHandler(conf database.ConfigManager, sess session.Session) *ConfigHandler {
return &ConfigHandler{conf, sess} return &ConfigHandler{conf, sess}
} }
@ -27,7 +27,7 @@ func (h *ConfigHandler) GetConfig(w http.ResponseWriter, r *http.Request) error
return notAuthorized{} return notAuthorized{}
} }
return json.NewEncoder(w).Encode(h.conf) return json.NewEncoder(w).Encode(h.conf.Find())
} }
func (h *ConfigHandler) Register(r *pat.Router) { func (h *ConfigHandler) Register(r *pat.Router) {

View file

@ -5,7 +5,6 @@ import (
"github.com/drone/drone/server/database" "github.com/drone/drone/server/database"
"github.com/drone/drone/server/queue" "github.com/drone/drone/server/queue"
"github.com/drone/drone/server/resource/config"
"github.com/drone/drone/shared/model" "github.com/drone/drone/shared/model"
"github.com/gorilla/pat" "github.com/gorilla/pat"
) )
@ -14,12 +13,12 @@ type HookHandler struct {
users database.UserManager users database.UserManager
repos database.RepoManager repos database.RepoManager
commits database.CommitManager commits database.CommitManager
conf database.ConfigManager
queue *queue.Queue queue *queue.Queue
conf *config.Config
} }
func NewHookHandler(users database.UserManager, repos database.RepoManager, commits database.CommitManager, conf *config.Config, queue *queue.Queue) *HookHandler { func NewHookHandler(users database.UserManager, repos database.RepoManager, commits database.CommitManager, conf database.ConfigManager, queue *queue.Queue) *HookHandler {
return &HookHandler{users, repos, commits, queue, conf} return &HookHandler{users, repos, commits, conf, queue}
} }
// PostHook receives a post-commit hook from GitHub, Bitbucket, etc // PostHook receives a post-commit hook from GitHub, Bitbucket, etc
@ -28,7 +27,7 @@ func (h *HookHandler) PostHook(w http.ResponseWriter, r *http.Request) error {
host := r.FormValue(":host") host := r.FormValue(":host")
// get the remote system's client. // get the remote system's client.
remote := h.conf.GetRemote(host) remote := h.conf.Find().GetRemote(host)
if remote == nil { if remote == nil {
return notFound{} return notFound{}
} }

View file

@ -6,7 +6,6 @@ import (
"time" "time"
"github.com/drone/drone/server/database" "github.com/drone/drone/server/database"
"github.com/drone/drone/server/resource/config"
"github.com/drone/drone/server/session" "github.com/drone/drone/server/session"
"github.com/drone/drone/shared/model" "github.com/drone/drone/shared/model"
"github.com/gorilla/pat" "github.com/gorilla/pat"
@ -16,12 +15,12 @@ type LoginHandler struct {
users database.UserManager users database.UserManager
repos database.RepoManager repos database.RepoManager
perms database.PermManager perms database.PermManager
conf database.ConfigManager
sess session.Session sess session.Session
conf *config.Config
} }
func NewLoginHandler(users database.UserManager, repos database.RepoManager, perms database.PermManager, sess session.Session, conf *config.Config) *LoginHandler { func NewLoginHandler(users database.UserManager, repos database.RepoManager, perms database.PermManager, sess session.Session, conf database.ConfigManager) *LoginHandler {
return &LoginHandler{users, repos, perms, sess, conf} return &LoginHandler{users, repos, perms, conf, sess}
} }
// GetLogin gets the login to the 3rd party remote system. // GetLogin gets the login to the 3rd party remote system.
@ -30,7 +29,7 @@ func (h *LoginHandler) GetLogin(w http.ResponseWriter, r *http.Request) error {
host := r.FormValue(":host") host := r.FormValue(":host")
// get the remote system's client. // get the remote system's client.
remote := h.conf.GetRemote(host) remote := h.conf.Find().GetRemote(host)
if remote == nil { if remote == nil {
return notFound{} return notFound{}
} }
@ -50,7 +49,7 @@ func (h *LoginHandler) GetLogin(w http.ResponseWriter, r *http.Request) error {
if err != nil { if err != nil {
// if self-registration is disabled we should // if self-registration is disabled we should
// return a notAuthorized error // return a notAuthorized error
if !h.conf.Registration { if !h.conf.Find().Registration {
return notAuthorized{} return notAuthorized{}
} }

View file

@ -6,7 +6,6 @@ import (
"net/http" "net/http"
"github.com/drone/drone/server/database" "github.com/drone/drone/server/database"
"github.com/drone/drone/server/resource/config"
"github.com/drone/drone/server/session" "github.com/drone/drone/server/session"
"github.com/drone/drone/shared/httputil" "github.com/drone/drone/shared/httputil"
"github.com/drone/drone/shared/sshutil" "github.com/drone/drone/shared/sshutil"
@ -14,7 +13,7 @@ import (
) )
type RepoHandler struct { type RepoHandler struct {
conf *config.Config conf database.ConfigManager
commits database.CommitManager commits database.CommitManager
perms database.PermManager perms database.PermManager
repos database.RepoManager repos database.RepoManager
@ -22,7 +21,7 @@ type RepoHandler struct {
} }
func NewRepoHandler(repos database.RepoManager, commits database.CommitManager, func NewRepoHandler(repos database.RepoManager, commits database.CommitManager,
perms database.PermManager, sess session.Session, conf *config.Config) *RepoHandler { perms database.PermManager, sess session.Session, conf database.ConfigManager) *RepoHandler {
return &RepoHandler{conf, commits, perms, repos, sess} return &RepoHandler{conf, commits, perms, repos, sess}
} }
@ -87,7 +86,7 @@ func (h *RepoHandler) PostRepo(w http.ResponseWriter, r *http.Request) error {
repo.PrivateKey = sshutil.MarshalPrivateKey(key) repo.PrivateKey = sshutil.MarshalPrivateKey(key)
// get the remote and client // get the remote and client
remote := h.conf.GetRemote(host) remote := h.conf.Find().GetRemote(host)
if remote == nil { if remote == nil {
return notFound{} return notFound{}
} }

View file

@ -4,7 +4,11 @@ import (
"database/sql" "database/sql"
"flag" "flag"
"html/template" "html/template"
"io/ioutil"
"net/http" "net/http"
"os"
"os/user"
"path/filepath"
"runtime" "runtime"
"time" "time"
@ -14,7 +18,6 @@ import (
"github.com/drone/drone/server/database/schema" "github.com/drone/drone/server/database/schema"
"github.com/drone/drone/server/handler" "github.com/drone/drone/server/handler"
"github.com/drone/drone/server/queue" "github.com/drone/drone/server/queue"
"github.com/drone/drone/server/resource/config"
"github.com/drone/drone/server/session" "github.com/drone/drone/server/session"
"github.com/drone/drone/shared/build/docker" "github.com/drone/drone/shared/build/docker"
"github.com/drone/drone/shared/build/log" "github.com/drone/drone/shared/build/log"
@ -27,6 +30,9 @@ import (
) )
var ( var (
// home directory for the application.
home string
// port the server will run on // port the server will run on
port string port string
@ -54,10 +60,6 @@ var (
workers int workers int
) )
// drone cofiguration data, loaded from the
// $HOME/.drone/config.toml file.
var conf config.Config
func main() { func main() {
log.SetPriority(log.LOG_NOTICE) log.SetPriority(log.LOG_NOTICE)
@ -78,6 +80,7 @@ func main() {
// template.New("_").Funcs(render.FuncMap).ParseGlob("template/html/*.html"), // template.New("_").Funcs(render.FuncMap).ParseGlob("template/html/*.html"),
//).ExecuteTemplate //).ExecuteTemplate
// load the html templates
templateBox := rice.MustFindBox("template/html") templateBox := rice.MustFindBox("template/html")
templateFiles := []string{"login.html", "repo_branch.html", "repo_commit.html", "repo_conf.html", "repo_feed.html", "user_conf.html", "user_feed.html", "user_login.html", "user_repos.html", "404.html", "400.html"} templateFiles := []string{"login.html", "repo_branch.html", "repo_commit.html", "repo_conf.html", "repo_feed.html", "user_conf.html", "user_feed.html", "user_login.html", "user_repos.html", "404.html", "400.html"}
templ := template.New("_").Funcs(funcMap) templ := template.New("_").Funcs(funcMap)
@ -96,6 +99,7 @@ func main() {
users := database.NewUserManager(db) users := database.NewUserManager(db)
perms := database.NewPermManager(db) perms := database.NewPermManager(db)
commits := database.NewCommitManager(db) commits := database.NewCommitManager(db)
configs := database.NewConfigManager(filepath.Join(home, "config.toml"))
// cancel all previously running builds // cancel all previously running builds
go commits.CancelAll() go commits.CancelAll()
@ -111,13 +115,13 @@ func main() {
router := pat.New() router := pat.New()
handler.NewUsersHandler(users, sess).Register(router) handler.NewUsersHandler(users, sess).Register(router)
handler.NewUserHandler(users, repos, commits, sess).Register(router) handler.NewUserHandler(users, repos, commits, sess).Register(router)
handler.NewHookHandler(users, repos, commits, &conf, queue).Register(router) handler.NewHookHandler(users, repos, commits, configs, queue).Register(router)
handler.NewLoginHandler(users, repos, perms, sess, &conf).Register(router) handler.NewLoginHandler(users, repos, perms, sess, configs).Register(router)
handler.NewCommitHandler(repos, commits, perms, sess, queue).Register(router) handler.NewCommitHandler(repos, commits, perms, sess, queue).Register(router)
handler.NewBranchHandler(repos, commits, perms, sess).Register(router) handler.NewBranchHandler(repos, commits, perms, sess).Register(router)
handler.NewRepoHandler(repos, commits, perms, sess, &conf).Register(router) handler.NewRepoHandler(repos, commits, perms, sess, configs).Register(router)
handler.NewBadgeHandler(repos, commits).Register(router) handler.NewBadgeHandler(repos, commits).Register(router)
handler.NewConfigHandler(conf, sess).Register(router) handler.NewConfigHandler(configs, sess).Register(router)
handler.NewSiteHandler(users, repos, commits, perms, sess, templ.ExecuteTemplate).Register(router) handler.NewSiteHandler(users, repos, commits, perms, sess, templ.ExecuteTemplate).Register(router)
// serve static assets // serve static assets
@ -139,3 +143,74 @@ func main() {
panic(http.ListenAndServe(port, nil)) panic(http.ListenAndServe(port, nil))
} }
} }
// initialize the .drone directory and create a skeleton config
// file if one does not already exist.
func init() {
// load the current user
u, err := user.Current()
if err != nil {
panic(err)
}
// set .drone home dir
home = filepath.Join(u.HomeDir, ".drone")
// create the .drone home directory
os.MkdirAll(home, 0777)
// check for the config file
filename := filepath.Join(u.HomeDir, ".drone", "config.toml")
if _, err := os.Stat(filename); err != nil {
// if not exists, create
ioutil.WriteFile(filename, []byte(defaultConfig), 0777)
}
}
var defaultConfig = `
# Enables user self-registration. If false, the system administrator
# will need to manually add users to the system.
registration = true
[smtp]
host = ""
port = ""
from = ""
username = ""
password = ""
[bitbucket]
url = "https://bitbucket.org"
api = "https://bitbucket.org"
client = ""
secret = ""
enabled = false
[github]
url = "https://github.com"
api = "https://api.github.com"
client = ""
secret = ""
enabled = false
[githubenterprise]
url = ""
api = ""
client = ""
secret = ""
enabled = false
[gitlab]
url = ""
api = ""
client = ""
secret = ""
enabled = false
[stash]
url = ""
api = ""
client = ""
secret = ""
enabled = false
`

View file

@ -1,34 +0,0 @@
package config
type ConfigManager interface {
Find() (*Config, error)
Must() *Config
}
// configManager manages configuration data from a combination
// of command line args and .ini files.
type configManager struct {
dir string
conf *Config
}
// NewManager initiales a new CommitManager intended to
// manage and persist commits.
func NewManager(dir string) ConfigManager {
conf := Config{}
//conf.Host = "localhost"
//conf.Scheme = "http"
return &configManager{dir, &conf}
}
func (c *configManager) Find() (*Config, error) {
return nil, nil
}
func (c *configManager) Must() *Config {
conf, err := c.Find()
if err != nil {
panic(err)
}
return conf
}

View file

@ -1,94 +0,0 @@
package config
import (
"github.com/drone/drone/plugin/remote"
"github.com/drone/drone/plugin/remote/bitbucket"
"github.com/drone/drone/plugin/remote/github"
"github.com/drone/drone/plugin/remote/gitlab"
"github.com/drone/drone/plugin/remote/stash"
"github.com/drone/drone/plugin/smtp"
)
type Config struct {
// Hostname of the server, eg drone.io
//Host string `json:"host"`
// Scheme of the server, eg https
//Scheme string `json:"scheme"`
// Registration with a value of True allows developers
// to register themselves. If false, must be approved
// or invited by the system administrator.
Registration bool `json:"registration"`
// SMTP stores configuration details for connecting with
// and smtp server to send email notifications.
SMTP *smtp.SMTP `json:"smtp"`
// Bitbucket stores configuration details for communicating
// with the bitbucket.org public cloud service.
Bitbucket *bitbucket.Bitbucket `json:"bitbucket"`
// Github stores configuration details for communicating
// with the github.com public cloud service.
Github *github.Github `json:"github"`
// GithubEnterprise stores configuration details for
// communicating with a private Github installation.
GithubEnterprise *github.Github `json:"githubEnterprise"`
// Gitlab stores configuration details for communicating
// with a private gitlab installation.
Gitlab *gitlab.Gitlab `json:"gitlab"`
// Stash stores configuration details for communicating
// with a private Atlassian Stash installation.
Stash *stash.Stash `json:"stash"`
}
// GetRemote is a helper function that will return the
// remote plugin name based on the specified hostname.
func (c *Config) GetRemote(name string) remote.Remote {
// first attempt to get the remote instance
// by the unique plugin name (ie enterprise.github.com)
switch name {
case c.Github.GetName():
return c.Github
case c.Bitbucket.GetName():
return c.Bitbucket
case c.GithubEnterprise.GetName():
return c.GithubEnterprise
case c.Gitlab.GetName():
return c.Gitlab
case c.Stash.GetName():
return c.Stash
}
// else attempt to get the remote instance
// by the hostname (ie github.drone.io)
switch {
case c.Github.IsMatch(name):
return c.Github
case c.Bitbucket.IsMatch(name):
return c.Bitbucket
case c.GithubEnterprise.IsMatch(name):
return c.GithubEnterprise
case c.Gitlab.IsMatch(name):
return c.Gitlab
case c.Stash.IsMatch(name):
return c.Stash
}
// else none found
return nil
}
// GetClient is a helper function taht will return the named
// remote plugin client, used to interact with the remote system.
func (c *Config) GetClient(name, access, secret string) remote.Client {
remote := c.GetRemote(name)
if remote == nil {
return nil
}
return remote.GetClient(access, secret)
}

View file

@ -1,39 +0,0 @@
package config
import (
"fmt"
"testing"
"github.com/BurntSushi/toml"
)
func TestRead(t *testing.T) {
var data = `
scheme = "https"
host = "localhost"
port = 8080
open = true
[github]
url = "https://github.com"
api = "https://api.github.com"
[bitbucket]
url = "https://bitbucket.org"
[smtp]
host = "smtp.drone.io"
port = "443"
user = "brad"
from = "brad@drone.io"
`
var conf Config
if _, err := toml.Decode(data, &conf); err != nil {
println(err.Error())
return
}
fmt.Printf("%#v\n", conf)
}

View file

@ -1 +1,94 @@
package model package model
import (
"github.com/drone/drone/plugin/remote"
"github.com/drone/drone/plugin/remote/bitbucket"
"github.com/drone/drone/plugin/remote/github"
"github.com/drone/drone/plugin/remote/gitlab"
"github.com/drone/drone/plugin/remote/stash"
"github.com/drone/drone/plugin/smtp"
)
type Config struct {
// Hostname of the server, eg drone.io
//Host string `json:"host"`
// Scheme of the server, eg https
//Scheme string `json:"scheme"`
// Registration with a value of True allows developers
// to register themselves. If false, must be approved
// or invited by the system administrator.
Registration bool `json:"registration"`
// SMTP stores configuration details for connecting with
// and smtp server to send email notifications.
SMTP *smtp.SMTP `json:"smtp"`
// Bitbucket stores configuration details for communicating
// with the bitbucket.org public cloud service.
Bitbucket *bitbucket.Bitbucket `json:"bitbucket"`
// Github stores configuration details for communicating
// with the github.com public cloud service.
Github *github.Github `json:"github"`
// GithubEnterprise stores configuration details for
// communicating with a private Github installation.
GithubEnterprise *github.Github `json:"githubEnterprise"`
// Gitlab stores configuration details for communicating
// with a private gitlab installation.
Gitlab *gitlab.Gitlab `json:"gitlab"`
// Stash stores configuration details for communicating
// with a private Atlassian Stash installation.
Stash *stash.Stash `json:"stash"`
}
// GetRemote is a helper function that will return the
// remote plugin name based on the specified hostname.
func (c *Config) GetRemote(name string) remote.Remote {
// first attempt to get the remote instance
// by the unique plugin name (ie enterprise.github.com)
switch name {
case c.Github.GetName():
return c.Github
case c.Bitbucket.GetName():
return c.Bitbucket
case c.GithubEnterprise.GetName():
return c.GithubEnterprise
case c.Gitlab.GetName():
return c.Gitlab
case c.Stash.GetName():
return c.Stash
}
// else attempt to get the remote instance
// by the hostname (ie github.drone.io)
switch {
case c.Github.IsMatch(name):
return c.Github
case c.Bitbucket.IsMatch(name):
return c.Bitbucket
case c.GithubEnterprise.IsMatch(name):
return c.GithubEnterprise
case c.Gitlab.IsMatch(name):
return c.Gitlab
case c.Stash.IsMatch(name):
return c.Stash
}
// else none found
return nil
}
// GetClient is a helper function taht will return the named
// remote plugin client, used to interact with the remote system.
func (c *Config) GetClient(name, access, secret string) remote.Client {
remote := c.GetRemote(name)
if remote == nil {
return nil
}
return remote.GetClient(access, secret)
}