diff --git a/.drone.sh b/.drone.sh index 53c9ea8fe..4da03600a 100755 --- a/.drone.sh +++ b/.drone.sh @@ -22,4 +22,5 @@ set -x git clone git@github.com:drone/drone-enterprise.git extras # build a static binary with the build number and extra features. -go build -ldflags '-extldflags "-static" -X github.com/drone/drone/version.VersionDev=build.'${DRONE_BUILD_NUMBER} -tags extras -o release/drone github.com/drone/drone/drone +go build -ldflags '-extldflags "-static" -X github.com/drone/drone/version.VersionDev=build.'${DRONE_BUILD_NUMBER} -o release/drone-server github.com/drone/drone/extras/cmd/drone-server +go build -ldflags '-extldflags "-static" -X github.com/drone/drone/version.VersionDev=build.'${DRONE_BUILD_NUMBER} -o release/drone-agent github.com/drone/drone/cmd/drone-agent diff --git a/.drone.yml b/.drone.yml index 6e7fb70d0..5e13a6305 100644 --- a/.drone.yml +++ b/.drone.yml @@ -37,7 +37,7 @@ pipeline: when: event: [ push, tag ] - publish: + publish_server: image: plugins/docker repo: drone/drone secrets: [ docker_username, docker_password ] @@ -46,7 +46,17 @@ pipeline: branch: master event: push - release: + publish_agent: + image: plugins/docker + repo: drone/agent + dockerfile: Dockerfile.agent + secrets: [ docker_username, docker_password ] + tag: [ latest ] + when: + branch: master + event: push + + release_server: image: plugins/docker repo: drone/drone secrets: [ docker_username, docker_password ] @@ -54,6 +64,15 @@ pipeline: when: event: tag + release_agent: + image: plugins/docker + repo: drone/agent + dockerfile: Dockerfile.agent + secrets: [ docker_username, docker_password ] + tag: [ 0.8, 0.8.0, 0.8.0-rc.1 ] + when: + event: tag + notify: image: plugins/gitter secrets: [ gitter_webhook ] diff --git a/Dockerfile b/Dockerfile index e18ac4a2d..fbafa0f75 100644 --- a/Dockerfile +++ b/Dockerfile @@ -8,7 +8,6 @@ ENV DATABASE_CONFIG=/var/lib/drone/drone.sqlite ENV GODEBUG=netdns=go ENV XDG_CACHE_HOME /var/lib/drone -ADD release/drone /drone +ADD release/drone-server /bin/ -ENTRYPOINT ["/drone"] -CMD ["server"] +ENTRYPOINT ["/bin/drone-server"] diff --git a/Dockerfile.agent b/Dockerfile.agent new file mode 100644 index 000000000..638d2e6d0 --- /dev/null +++ b/Dockerfile.agent @@ -0,0 +1,7 @@ +# docker build --rm -t drone/drone . + +FROM centurylink/ca-certs + +ADD release/drone-agent /bin/ + +ENTRYPOINT ["/bin/drone-agent"] diff --git a/Dockerfile.arm64 b/Dockerfile.arm64 deleted file mode 100644 index 87b5056ad..000000000 --- a/Dockerfile.arm64 +++ /dev/null @@ -1,11 +0,0 @@ -FROM ?????????? - -EXPOSE 8000 -ENV DATABASE_DRIVER=sqlite3 -ENV DATABASE_CONFIG=/var/lib/drone/drone.sqlite -ENV GODEBUG=netdns=go - -ADD release/linux/arm64/drone /drone - -ENTRYPOINT ["/drone"] -CMD ["server"] diff --git a/Dockerfile.armhf b/Dockerfile.armhf deleted file mode 100644 index 5917bb454..000000000 --- a/Dockerfile.armhf +++ /dev/null @@ -1,11 +0,0 @@ -FROM ?????????? - -EXPOSE 8000 -ENV DATABASE_DRIVER=sqlite3 -ENV DATABASE_CONFIG=/var/lib/drone/drone.sqlite -ENV GODEBUG=netdns=go - -ADD release/linux/arm/drone /drone - -ENTRYPOINT ["/drone"] -CMD ["server"] diff --git a/Dockerfile.windows b/Dockerfile.windows deleted file mode 100644 index 355cbce50..000000000 --- a/Dockerfile.windows +++ /dev/null @@ -1,11 +0,0 @@ -FROM ?????????? - -EXPOSE 8000 -ENV DATABASE_DRIVER=sqlite3 -ENV DATABASE_CONFIG=/var/lib/drone/drone.sqlite -ENV GODEBUG=netdns=go - -ADD release/windows/amd64/drone /drone - -ENTRYPOINT ["/drone"] -CMD ["server"] diff --git a/client/client.go b/client/client.go deleted file mode 100644 index b7554eaec..000000000 --- a/client/client.go +++ /dev/null @@ -1,117 +0,0 @@ -package client - -import ( - "io" - - "github.com/drone/drone/model" -) - -// Client is used to communicate with a Drone server. -type Client interface { - // Self returns the currently authenticated user. - Self() (*model.User, error) - - // User returns a user by login. - User(string) (*model.User, error) - - // UserList returns a list of all registered users. - UserList() ([]*model.User, error) - - // UserPost creates a new user account. - UserPost(*model.User) (*model.User, error) - - // UserPatch updates a user account. - UserPatch(*model.User) (*model.User, error) - - // UserDel deletes a user account. - UserDel(string) error - - // Repo returns a repository by name. - Repo(string, string) (*model.Repo, error) - - // RepoList returns a list of all repositories to which the user has explicit - // access in the host system. - RepoList() ([]*model.Repo, error) - - // RepoPost activates a repository. - RepoPost(string, string) (*model.Repo, error) - - // RepoPatch updates a repository. - RepoPatch(string, string, *model.RepoPatch) (*model.Repo, error) - - // RepoChown updates a repository owner. - RepoChown(string, string) (*model.Repo, error) - - // RepoRepair repairs the repository hooks. - RepoRepair(string, string) error - - // RepoDel deletes a repository. - RepoDel(string, string) error - - // Build returns a repository build by number. - Build(string, string, int) (*model.Build, error) - - // BuildLast returns the latest repository build by branch. An empty branch - // will result in the default branch. - BuildLast(string, string, string) (*model.Build, error) - - // BuildList returns a list of recent builds for the - // the specified repository. - BuildList(string, string) ([]*model.Build, error) - - // BuildQueue returns a list of enqueued builds. - BuildQueue() ([]*model.Feed, error) - - // BuildStart re-starts a stopped build. - BuildStart(string, string, int, map[string]string) (*model.Build, error) - - // BuildStop stops the specified running job for given build. - BuildStop(string, string, int, int) error - - // BuildFork re-starts a stopped build with a new build number, preserving - // the prior history. - BuildFork(string, string, int, map[string]string) (*model.Build, error) - - // BuildApprove approves a blocked build. - BuildApprove(string, string, int) (*model.Build, error) - - // BuildDecline declines a blocked build. - BuildDecline(string, string, int) (*model.Build, error) - - // BuildLogs returns the build logs for the specified job. - BuildLogs(string, string, int, int) (io.ReadCloser, error) - - // Deploy triggers a deployment for an existing build using the specified - // target environment. - Deploy(string, string, int, string, map[string]string) (*model.Build, error) - - // Registry returns a registry by hostname. - Registry(owner, name, hostname string) (*model.Registry, error) - - // RegistryList returns a list of all repository registries. - RegistryList(owner, name string) ([]*model.Registry, error) - - // RegistryCreate creates a registry. - RegistryCreate(owner, name string, registry *model.Registry) (*model.Registry, error) - - // RegistryUpdate updates a registry. - RegistryUpdate(owner, name string, registry *model.Registry) (*model.Registry, error) - - // RegistryDelete deletes a registry. - RegistryDelete(owner, name, hostname string) error - - // Secret returns a secret by name. - Secret(owner, name, secret string) (*model.Secret, error) - - // SecretList returns a list of all repository secrets. - SecretList(owner, name string) ([]*model.Secret, error) - - // SecretCreate creates a registry. - SecretCreate(owner, name string, secret *model.Secret) (*model.Secret, error) - - // SecretUpdate updates a registry. - SecretUpdate(owner, name string, secret *model.Secret) (*model.Secret, error) - - // SecretDelete deletes a secret. - SecretDelete(owner, name, secret string) error -} diff --git a/client/client_impl.go b/client/client_impl.go deleted file mode 100644 index cf5e51f86..000000000 --- a/client/client_impl.go +++ /dev/null @@ -1,501 +0,0 @@ -package client - -import ( - "bytes" - "crypto/tls" - "encoding/json" - "fmt" - "io" - "io/ioutil" - "net/http" - "net/url" - "os" - "strconv" - - "github.com/drone/drone/model" - "golang.org/x/net/proxy" - "golang.org/x/oauth2" -) - -const ( - pathPull = "%s/api/queue/pull/%s/%s" - pathWait = "%s/api/queue/wait/%d" - pathStream = "%s/api/queue/stream/%d" - pathPush = "%s/api/queue/status/%d" - pathPing = "%s/api/queue/ping" - pathLogs = "%s/api/queue/logs/%d" - pathLogsAuth = "%s/api/queue/logs/%d?access_token=%s" - - pathSelf = "%s/api/user" - pathFeed = "%s/api/user/feed" - pathRepos = "%s/api/user/repos" - pathRepo = "%s/api/repos/%s/%s" - pathChown = "%s/api/repos/%s/%s/chown" - pathRepair = "%s/api/repos/%s/%s/repair" - pathBuilds = "%s/api/repos/%s/%s/builds" - pathBuild = "%s/api/repos/%s/%s/builds/%v" - pathApprove = "%s/api/repos/%s/%s/builds/%d/approve" - pathDecline = "%s/api/repos/%s/%s/builds/%d/decline" - pathJob = "%s/api/repos/%s/%s/builds/%d/%d" - pathLog = "%s/api/repos/%s/%s/logs/%d/%d" - pathRepoSecrets = "%s/api/repos/%s/%s/secrets" - pathRepoSecret = "%s/api/repos/%s/%s/secrets/%s" - pathRepoRegistries = "%s/api/repos/%s/%s/registry" - pathRepoRegistry = "%s/api/repos/%s/%s/registry/%s" - pathUsers = "%s/api/users" - pathUser = "%s/api/users/%s" - pathBuildQueue = "%s/api/builds" -) - -type client struct { - client *http.Client - token string // auth token - base string // base url -} - -// NewClient returns a client at the specified url. -func NewClient(uri string) Client { - return &client{client: http.DefaultClient, base: uri} -} - -// NewClientToken returns a client at the specified url that authenticates all -// outbound requests with the given token. -func NewClientToken(uri, token string) Client { - config := new(oauth2.Config) - auther := config.Client(oauth2.NoContext, &oauth2.Token{AccessToken: token}) - return &client{client: auther, base: uri, token: token} -} - -// NewClientTokenTLS returns a client at the specified url that authenticates -// all outbound requests with the given token and tls.Config if provided. -func NewClientTokenTLS(uri, token string, c *tls.Config) (Client, error) { - config := new(oauth2.Config) - auther := config.Client(oauth2.NoContext, &oauth2.Token{AccessToken: token}) - if c != nil { - if trans, ok := auther.Transport.(*oauth2.Transport); ok { - if os.Getenv("SOCKS_PROXY") != "" { - dialer, err := proxy.SOCKS5("tcp", os.Getenv("SOCKS_PROXY"), nil, proxy.Direct) - if err != nil { - return nil, err - } - trans.Base = &http.Transport{ - TLSClientConfig: c, - Proxy: http.ProxyFromEnvironment, - Dial: dialer.Dial, - } - } else { - trans.Base = &http.Transport{ - TLSClientConfig: c, - Proxy: http.ProxyFromEnvironment, - } - } - } - } - return &client{client: auther, base: uri, token: token}, nil -} - -// Self returns the currently authenticated user. -func (c *client) Self() (*model.User, error) { - out := new(model.User) - uri := fmt.Sprintf(pathSelf, c.base) - err := c.get(uri, out) - return out, err -} - -// User returns a user by login. -func (c *client) User(login string) (*model.User, error) { - out := new(model.User) - uri := fmt.Sprintf(pathUser, c.base, login) - err := c.get(uri, out) - return out, err -} - -// UserList returns a list of all registered users. -func (c *client) UserList() ([]*model.User, error) { - var out []*model.User - uri := fmt.Sprintf(pathUsers, c.base) - err := c.get(uri, &out) - return out, err -} - -// UserPost creates a new user account. -func (c *client) UserPost(in *model.User) (*model.User, error) { - out := new(model.User) - uri := fmt.Sprintf(pathUsers, c.base) - err := c.post(uri, in, out) - return out, err -} - -// UserPatch updates a user account. -func (c *client) UserPatch(in *model.User) (*model.User, error) { - out := new(model.User) - uri := fmt.Sprintf(pathUser, c.base, in.Login) - err := c.patch(uri, in, out) - return out, err -} - -// UserDel deletes a user account. -func (c *client) UserDel(login string) error { - uri := fmt.Sprintf(pathUser, c.base, login) - err := c.delete(uri) - return err -} - -// Repo returns a repository by name. -func (c *client) Repo(owner string, name string) (*model.Repo, error) { - out := new(model.Repo) - uri := fmt.Sprintf(pathRepo, c.base, owner, name) - err := c.get(uri, out) - return out, err -} - -// RepoList returns a list of all repositories to which -// the user has explicit access in the host system. -func (c *client) RepoList() ([]*model.Repo, error) { - var out []*model.Repo - uri := fmt.Sprintf(pathRepos, c.base) - err := c.get(uri, &out) - return out, err -} - -// RepoPost activates a repository. -func (c *client) RepoPost(owner string, name string) (*model.Repo, error) { - out := new(model.Repo) - uri := fmt.Sprintf(pathRepo, c.base, owner, name) - err := c.post(uri, nil, out) - return out, err -} - -// RepoChown updates a repository owner. -func (c *client) RepoChown(owner string, name string) (*model.Repo, error) { - out := new(model.Repo) - uri := fmt.Sprintf(pathChown, c.base, owner, name) - err := c.post(uri, nil, out) - return out, err -} - -// RepoRepair repais the repository hooks. -func (c *client) RepoRepair(owner string, name string) error { - uri := fmt.Sprintf(pathRepair, c.base, owner, name) - return c.post(uri, nil, nil) -} - -// RepoPatch updates a repository. -func (c *client) RepoPatch(owner, name string, in *model.RepoPatch) (*model.Repo, error) { - out := new(model.Repo) - uri := fmt.Sprintf(pathRepo, c.base, owner, name) - err := c.patch(uri, in, out) - return out, err -} - -// RepoDel deletes a repository. -func (c *client) RepoDel(owner, name string) error { - uri := fmt.Sprintf(pathRepo, c.base, owner, name) - err := c.delete(uri) - return err -} - -// Build returns a repository build by number. -func (c *client) Build(owner, name string, num int) (*model.Build, error) { - out := new(model.Build) - uri := fmt.Sprintf(pathBuild, c.base, owner, name, num) - err := c.get(uri, out) - return out, err -} - -// Build returns the latest repository build by branch. -func (c *client) BuildLast(owner, name, branch string) (*model.Build, error) { - out := new(model.Build) - uri := fmt.Sprintf(pathBuild, c.base, owner, name, "latest") - if len(branch) != 0 { - uri += "?branch=" + branch - } - err := c.get(uri, out) - return out, err -} - -// BuildList returns a list of recent builds for the -// the specified repository. -func (c *client) BuildList(owner, name string) ([]*model.Build, error) { - var out []*model.Build - uri := fmt.Sprintf(pathBuilds, c.base, owner, name) - err := c.get(uri, &out) - return out, err -} - -// BuildQueue returns a list of enqueued builds. -func (c *client) BuildQueue() ([]*model.Feed, error) { - var out []*model.Feed - uri := fmt.Sprintf(pathBuildQueue, c.base) - err := c.get(uri, &out) - return out, err -} - -// BuildStart re-starts a stopped build. -func (c *client) BuildStart(owner, name string, num int, params map[string]string) (*model.Build, error) { - out := new(model.Build) - val := parseToQueryParams(params) - uri := fmt.Sprintf(pathBuild, c.base, owner, name, num) - err := c.post(uri+"?"+val.Encode(), nil, out) - return out, err -} - -// BuildStop cancels the running job. -func (c *client) BuildStop(owner, name string, num, job int) error { - uri := fmt.Sprintf(pathJob, c.base, owner, name, num, job) - err := c.delete(uri) - return err -} - -// BuildFork re-starts a stopped build with a new build number, -// preserving the prior history. -func (c *client) BuildFork(owner, name string, num int, params map[string]string) (*model.Build, error) { - out := new(model.Build) - val := parseToQueryParams(params) - val.Set("fork", "true") - uri := fmt.Sprintf(pathBuild, c.base, owner, name, num) - err := c.post(uri+"?"+val.Encode(), nil, out) - return out, err -} - -// BuildApprove approves a blocked build. -func (c *client) BuildApprove(owner, name string, num int) (*model.Build, error) { - out := new(model.Build) - uri := fmt.Sprintf(pathApprove, c.base, owner, name, num) - err := c.post(uri, nil, out) - return out, err -} - -// BuildDecline declines a blocked build. -func (c *client) BuildDecline(owner, name string, num int) (*model.Build, error) { - out := new(model.Build) - uri := fmt.Sprintf(pathDecline, c.base, owner, name, num) - err := c.post(uri, nil, out) - return out, err -} - -// BuildLogs returns the build logs for the specified job. -func (c *client) BuildLogs(owner, name string, num, job int) (io.ReadCloser, error) { - uri := fmt.Sprintf(pathLog, c.base, owner, name, num, job) - return stream(c.client, uri, "GET", nil, nil) -} - -// Deploy triggers a deployment for an existing build using the -// specified target environment. -func (c *client) Deploy(owner, name string, num int, env string, params map[string]string) (*model.Build, error) { - out := new(model.Build) - val := parseToQueryParams(params) - val.Set("fork", "true") - val.Set("event", "deployment") - val.Set("deploy_to", env) - uri := fmt.Sprintf(pathBuild, c.base, owner, name, num) - err := c.post(uri+"?"+val.Encode(), nil, out) - return out, err -} - -// Registry returns a registry by hostname. -func (c *client) Registry(owner, name, hostname string) (*model.Registry, error) { - out := new(model.Registry) - uri := fmt.Sprintf(pathRepoRegistry, c.base, owner, name, hostname) - err := c.get(uri, out) - return out, err -} - -// RegistryList returns a list of all repository registries. -func (c *client) RegistryList(owner string, name string) ([]*model.Registry, error) { - var out []*model.Registry - uri := fmt.Sprintf(pathRepoRegistries, c.base, owner, name) - err := c.get(uri, &out) - return out, err -} - -// RegistryCreate creates a registry. -func (c *client) RegistryCreate(owner, name string, in *model.Registry) (*model.Registry, error) { - out := new(model.Registry) - uri := fmt.Sprintf(pathRepoRegistries, c.base, owner, name) - err := c.post(uri, in, out) - return out, err -} - -// RegistryUpdate updates a registry. -func (c *client) RegistryUpdate(owner, name string, in *model.Registry) (*model.Registry, error) { - out := new(model.Registry) - uri := fmt.Sprintf(pathRepoRegistry, c.base, owner, name, in.Address) - err := c.patch(uri, in, out) - return out, err -} - -// RegistryDelete deletes a registry. -func (c *client) RegistryDelete(owner, name, hostname string) error { - uri := fmt.Sprintf(pathRepoRegistry, c.base, owner, name, hostname) - return c.delete(uri) -} - -// Secret returns a secret by name. -func (c *client) Secret(owner, name, secret string) (*model.Secret, error) { - out := new(model.Secret) - uri := fmt.Sprintf(pathRepoSecret, c.base, owner, name, secret) - err := c.get(uri, out) - return out, err -} - -// SecretList returns a list of all repository secrets. -func (c *client) SecretList(owner string, name string) ([]*model.Secret, error) { - var out []*model.Secret - uri := fmt.Sprintf(pathRepoSecrets, c.base, owner, name) - err := c.get(uri, &out) - return out, err -} - -// SecretCreate creates a secret. -func (c *client) SecretCreate(owner, name string, in *model.Secret) (*model.Secret, error) { - out := new(model.Secret) - uri := fmt.Sprintf(pathRepoSecrets, c.base, owner, name) - err := c.post(uri, in, out) - return out, err -} - -// SecretUpdate updates a secret. -func (c *client) SecretUpdate(owner, name string, in *model.Secret) (*model.Secret, error) { - out := new(model.Secret) - uri := fmt.Sprintf(pathRepoSecret, c.base, owner, name, in.Name) - err := c.patch(uri, in, out) - return out, err -} - -// SecretDelete deletes a secret. -func (c *client) SecretDelete(owner, name, secret string) error { - uri := fmt.Sprintf(pathRepoSecret, c.base, owner, name, secret) - return c.delete(uri) -} - -// -// http request helper functions -// - -// helper function for making an http GET request. -func (c *client) get(rawurl string, out interface{}) error { - return c.do(rawurl, "GET", nil, out) -} - -// helper function for making an http POST request. -func (c *client) post(rawurl string, in, out interface{}) error { - return c.do(rawurl, "POST", in, out) -} - -// helper function for making an http PUT request. -func (c *client) put(rawurl string, in, out interface{}) error { - return c.do(rawurl, "PUT", in, out) -} - -// helper function for making an http PATCH request. -func (c *client) patch(rawurl string, in, out interface{}) error { - return c.do(rawurl, "PATCH", in, out) -} - -// helper function for making an http DELETE request. -func (c *client) delete(rawurl string) error { - return c.do(rawurl, "DELETE", nil, nil) -} - -// helper function to make an http request -func (c *client) do(rawurl, method string, in, out interface{}) error { - // executes the http request and returns the body as - // and io.ReadCloser - body, err := c.open(rawurl, method, in, out) - if err != nil { - return err - } - defer body.Close() - - // if a json response is expected, parse and return - // the json response. - if out != nil { - return json.NewDecoder(body).Decode(out) - } - return nil -} - -// helper function to open an http request -func (c *client) open(rawurl, method string, in, out interface{}) (io.ReadCloser, error) { - uri, err := url.Parse(rawurl) - if err != nil { - return nil, err - } - - // creates a new http request to bitbucket. - req, err := http.NewRequest(method, uri.String(), nil) - if err != nil { - return nil, err - } - - // if we are posting or putting data, we need to - // write it to the body of the request. - if in != nil { - rc, ok := in.(io.ReadCloser) - if ok { - req.Body = rc - req.Header.Set("Content-Type", "plain/text") - } else { - inJson, err := json.Marshal(in) - if err != nil { - return nil, err - } - - buf := bytes.NewBuffer(inJson) - req.Body = ioutil.NopCloser(buf) - - req.ContentLength = int64(len(inJson)) - req.Header.Set("Content-Length", strconv.Itoa(len(inJson))) - req.Header.Set("Content-Type", "application/json") - } - } - resp, err := c.client.Do(req) - if err != nil { - return nil, err - } - if resp.StatusCode > http.StatusPartialContent { - defer resp.Body.Close() - out, _ := ioutil.ReadAll(resp.Body) - return nil, fmt.Errorf("client error %d: %s", resp.StatusCode, string(out)) - } - return resp.Body, nil -} - -// createRequest is a helper function that builds an http.Request. -func (c *client) createRequest(rawurl, method string, in interface{}) (*http.Request, error) { - uri, err := url.Parse(rawurl) - if err != nil { - return nil, err - } - - // if we are posting or putting data, we need to - // write it to the body of the request. - var buf io.ReadWriter - if in != nil { - buf = new(bytes.Buffer) - err := json.NewEncoder(buf).Encode(in) - if err != nil { - return nil, err - } - } - - // creates a new http request to bitbucket. - req, err := http.NewRequest(method, uri.String(), buf) - if err != nil { - return nil, err - } - if in != nil { - req.Header.Set("Content-Type", "application/json") - } - return req, nil -} - -// parseToQueryParams parses a map of strings and returns url.Values -func parseToQueryParams(p map[string]string) url.Values { - values := url.Values{} - for k, v := range p { - values.Add(k, v) - } - return values -} diff --git a/client/http.go b/client/http.go deleted file mode 100644 index d62da4b0f..000000000 --- a/client/http.go +++ /dev/null @@ -1,61 +0,0 @@ -package client - -import ( - "bytes" - "encoding/json" - "fmt" - "io" - "io/ioutil" - "net/http" - "net/url" -) - -// helper function to stream an http request -func stream(client *http.Client, rawurl, method string, in, out interface{}) (io.ReadCloser, error) { - uri, err := url.Parse(rawurl) - if err != nil { - return nil, err - } - - // if we are posting or putting data, we need to - // write it to the body of the request. - var buf io.ReadWriter - if in == nil { - // nothing - } else if rw, ok := in.(io.ReadWriter); ok { - buf = rw - } else if b, ok := in.([]byte); ok { - buf = new(bytes.Buffer) - buf.Write(b) - } else { - buf = new(bytes.Buffer) - err := json.NewEncoder(buf).Encode(in) - if err != nil { - return nil, err - } - } - - // creates a new http request to bitbucket. - req, err := http.NewRequest(method, uri.String(), buf) - if err != nil { - return nil, err - } - if in == nil { - // nothing - } else if _, ok := in.(io.ReadWriter); ok { - req.Header.Set("Content-Type", "plain/text") - } else { - req.Header.Set("Content-Type", "application/json") - } - - resp, err := client.Do(req) - if err != nil { - return nil, err - } - if resp.StatusCode > http.StatusPartialContent { - defer resp.Body.Close() - out, _ := ioutil.ReadAll(resp.Body) - return nil, fmt.Errorf(string(out)) - } - return resp.Body, nil -} diff --git a/drone/agent/agent.go b/cmd/drone-agent/agent.go similarity index 91% rename from drone/agent/agent.go rename to cmd/drone-agent/agent.go index ebc8c4782..6319055b9 100644 --- a/drone/agent/agent.go +++ b/cmd/drone-agent/agent.go @@ -1,4 +1,4 @@ -package agent +package main import ( "context" @@ -23,41 +23,6 @@ import ( "github.com/urfave/cli" ) -// Command exports the agent command. -var Command = cli.Command{ - Name: "agent", - Usage: "starts the drone agent", - Action: loop, - Flags: []cli.Flag{ - cli.StringFlag{ - EnvVar: "DRONE_SERVER", - Name: "server", - Usage: "drone server address", - Value: "localhost:9000", - }, - cli.StringFlag{ - EnvVar: "DRONE_SECRET", - Name: "secret", - Usage: "drone agent secret", - }, - cli.BoolFlag{ - EnvVar: "DRONE_DEBUG", - Name: "debug", - Usage: "start the agent in debug mode", - }, - cli.StringFlag{ - EnvVar: "DRONE_PLATFORM", - Name: "platform", - Value: "linux/amd64", - }, - cli.IntFlag{ - EnvVar: "DRONE_MAX_PROCS", - Name: "max-procs", - Value: 1, - }, - }, -} - func loop(c *cli.Context) error { // endpoint, err := url.Parse( // c.String("drone-server"), diff --git a/cmd/drone-agent/main.go b/cmd/drone-agent/main.go new file mode 100644 index 000000000..aeff90e82 --- /dev/null +++ b/cmd/drone-agent/main.go @@ -0,0 +1,52 @@ +package main + +import ( + "fmt" + "os" + + "github.com/drone/drone/version" + + _ "github.com/joho/godotenv/autoload" + "github.com/urfave/cli" +) + +func main() { + app := cli.NewApp() + app.Name = "drone-agent" + app.Version = version.Version.String() + app.Usage = "drone agent" + app.Action = loop + app.Flags = []cli.Flag{ + cli.StringFlag{ + EnvVar: "DRONE_SERVER", + Name: "server", + Usage: "drone server address", + Value: "localhost:9000", + }, + cli.StringFlag{ + EnvVar: "DRONE_SECRET", + Name: "secret", + Usage: "drone agent secret", + }, + cli.BoolFlag{ + EnvVar: "DRONE_DEBUG", + Name: "debug", + Usage: "start the agent in debug mode", + }, + cli.StringFlag{ + EnvVar: "DRONE_PLATFORM", + Name: "platform", + Value: "linux/amd64", + }, + cli.IntFlag{ + EnvVar: "DRONE_MAX_PROCS", + Name: "max-procs", + Value: 1, + }, + } + + if err := app.Run(os.Args); err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } +} diff --git a/cmd/drone-server/main.go b/cmd/drone-server/main.go new file mode 100644 index 000000000..af2137f5c --- /dev/null +++ b/cmd/drone-server/main.go @@ -0,0 +1,26 @@ +package main + +import ( + "fmt" + "os" + + "github.com/drone/drone/version" + + _ "github.com/joho/godotenv/autoload" + "github.com/urfave/cli" +) + +func main() { + app := cli.NewApp() + app.Name = "drone-server" + app.Version = version.Version.String() + app.Usage = "drone server" + app.Action = server + app.Flags = flags + app.Before = before + + if err := app.Run(os.Args); err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } +} diff --git a/cmd/drone-server/server.go b/cmd/drone-server/server.go new file mode 100644 index 000000000..3c0a04bc6 --- /dev/null +++ b/cmd/drone-server/server.go @@ -0,0 +1,529 @@ +package main + +import ( + "context" + "net" + "net/http" + "net/url" + "strings" + "time" + + "google.golang.org/grpc" + + "golang.org/x/crypto/acme/autocert" + "golang.org/x/sync/errgroup" + + "github.com/cncd/logging" + "github.com/cncd/pipeline/pipeline/rpc/proto" + "github.com/cncd/pubsub" + "github.com/drone/drone/plugins/registry" + "github.com/drone/drone/plugins/secrets" + "github.com/drone/drone/plugins/sender" + "github.com/drone/drone/remote" + "github.com/drone/drone/router" + "github.com/drone/drone/router/middleware" + droneserver "github.com/drone/drone/server" + "github.com/drone/drone/store" + + "github.com/Sirupsen/logrus" + "github.com/gin-gonic/contrib/ginrus" + "github.com/urfave/cli" +) + +var flags = []cli.Flag{ + cli.BoolFlag{ + EnvVar: "DRONE_DEBUG", + Name: "debug", + Usage: "start the server in debug mode", + }, + cli.StringFlag{ + EnvVar: "DRONE_SERVER_HOST,DRONE_HOST", + Name: "server-host", + Usage: "server host", + }, + cli.StringFlag{ + EnvVar: "DRONE_SERVER_ADDR", + Name: "server-addr", + Usage: "server address", + Value: ":8000", + }, + cli.StringFlag{ + EnvVar: "DRONE_SERVER_CERT", + Name: "server-cert", + Usage: "server ssl cert", + }, + cli.StringFlag{ + EnvVar: "DRONE_SERVER_KEY", + Name: "server-key", + Usage: "server ssl key", + }, + cli.BoolFlag{ + EnvVar: "DRONE_LETS_ENCRYPT", + Name: "lets-encrypt", + Usage: "lets encrypt enabled", + }, + cli.StringSliceFlag{ + EnvVar: "DRONE_ADMIN", + Name: "admin", + Usage: "list of admin users", + }, + cli.StringSliceFlag{ + EnvVar: "DRONE_ORGS", + Name: "orgs", + Usage: "list of approved organizations", + }, + cli.BoolFlag{ + EnvVar: "DRONE_OPEN", + Name: "open", + Usage: "open user registration", + }, + cli.DurationFlag{ + EnvVar: "DRONE_CACHE_TTL", + Name: "cache-ttl", + Usage: "cache duration", + Value: time.Minute * 15, + }, + cli.StringSliceFlag{ + EnvVar: "DRONE_ESCALATE", + Name: "escalate", + Value: &cli.StringSlice{ + "plugins/docker", + "plugins/gcr", + "plugins/ecr", + }, + }, + cli.StringSliceFlag{ + EnvVar: "DRONE_VOLUME", + Name: "volume", + }, + cli.StringSliceFlag{ + EnvVar: "DRONE_NETWORK", + Name: "network", + }, + cli.StringFlag{ + EnvVar: "DRONE_AGENT_SECRET,DRONE_SECRET", + Name: "agent-secret", + Usage: "agent secret passcode", + }, + cli.StringFlag{ + EnvVar: "DRONE_SECRET_ENDPOINT", + Name: "secret-service", + Usage: "secret plugin endpoint", + }, + cli.StringFlag{ + EnvVar: "DRONE_REGISTRY_ENDPOINT", + Name: "registry-service", + Usage: "registry plugin endpoint", + }, + cli.StringFlag{ + EnvVar: "DRONE_GATEKEEPER_ENDPOINT", + Name: "gating-service", + Usage: "gated build endpoint", + }, + cli.StringFlag{ + EnvVar: "DRONE_DATABASE_DRIVER,DATABASE_DRIVER", + Name: "driver", + Usage: "database driver", + Value: "sqlite3", + }, + cli.StringFlag{ + EnvVar: "DRONE_DATABASE_DATASOURCE,DATABASE_CONFIG", + Name: "datasource", + Usage: "database driver configuration string", + Value: "drone.sqlite", + }, + // + // resource limit parameters + // + cli.Int64Flag{ + Name: "limit-mem-swap", + EnvVar: "DRONE_LIMIT_MEM_SWAP", + }, + cli.Int64Flag{ + Name: "limit-mem", + EnvVar: "DRONE_LIMIT_MEM", + }, + cli.Int64Flag{ + Name: "limit-shm-size", + EnvVar: "DRONE_LIMIT_SHM_SIZE", + }, + cli.Int64Flag{ + Name: "limit-cpu-quota", + EnvVar: "DRONE_LIMIT_CPU_QUOTA", + }, + cli.Int64Flag{ + Name: "limit-cpu-shares", + EnvVar: "DRONE_LIMIT_CPU_SHARES", + }, + cli.StringFlag{ + Name: "limit-cpu-set", + EnvVar: "DRONE_LIMIT_CPU_SET", + }, + // + // remote parameters + // + cli.BoolFlag{ + EnvVar: "DRONE_GITHUB", + Name: "github", + Usage: "github driver is enabled", + }, + cli.StringFlag{ + EnvVar: "DRONE_GITHUB_URL", + Name: "github-server", + Usage: "github server address", + Value: "https://github.com", + }, + cli.StringFlag{ + EnvVar: "DRONE_GITHUB_CONTEXT", + Name: "github-context", + Usage: "github status context", + Value: "continuous-integration/drone", + }, + cli.StringFlag{ + EnvVar: "DRONE_GITHUB_CLIENT", + Name: "github-client", + Usage: "github oauth2 client id", + }, + cli.StringFlag{ + EnvVar: "DRONE_GITHUB_SECRET", + Name: "github-secret", + Usage: "github oauth2 client secret", + }, + cli.StringSliceFlag{ + EnvVar: "DRONE_GITHUB_SCOPE", + Name: "github-scope", + Usage: "github oauth scope", + Value: &cli.StringSlice{ + "repo", + "repo:status", + "user:email", + "read:org", + }, + }, + cli.StringFlag{ + EnvVar: "DRONE_GITHUB_GIT_USERNAME", + Name: "github-git-username", + Usage: "github machine user username", + }, + cli.StringFlag{ + EnvVar: "DRONE_GITHUB_GIT_PASSWORD", + Name: "github-git-password", + Usage: "github machine user password", + }, + cli.BoolTFlag{ + EnvVar: "DRONE_GITHUB_MERGE_REF", + Name: "github-merge-ref", + Usage: "github pull requests use merge ref", + }, + cli.BoolFlag{ + EnvVar: "DRONE_GITHUB_PRIVATE_MODE", + Name: "github-private-mode", + Usage: "github is running in private mode", + }, + cli.BoolFlag{ + EnvVar: "DRONE_GITHUB_SKIP_VERIFY", + Name: "github-skip-verify", + Usage: "github skip ssl verification", + }, + cli.BoolFlag{ + EnvVar: "DRONE_GOGS", + Name: "gogs", + Usage: "gogs driver is enabled", + }, + cli.StringFlag{ + EnvVar: "DRONE_GOGS_URL", + Name: "gogs-server", + Usage: "gogs server address", + Value: "https://github.com", + }, + cli.StringFlag{ + EnvVar: "DRONE_GOGS_GIT_USERNAME", + Name: "gogs-git-username", + Usage: "gogs service account username", + }, + cli.StringFlag{ + EnvVar: "DRONE_GOGS_GIT_PASSWORD", + Name: "gogs-git-password", + Usage: "gogs service account password", + }, + cli.BoolFlag{ + EnvVar: "DRONE_GOGS_PRIVATE_MODE", + Name: "gogs-private-mode", + Usage: "gogs private mode enabled", + }, + cli.BoolFlag{ + EnvVar: "DRONE_GOGS_SKIP_VERIFY", + Name: "gogs-skip-verify", + Usage: "gogs skip ssl verification", + }, + cli.BoolFlag{ + EnvVar: "DRONE_GITEA", + Name: "gitea", + Usage: "gitea driver is enabled", + }, + cli.StringFlag{ + EnvVar: "DRONE_GITEA_URL", + Name: "gitea-server", + Usage: "gitea server address", + Value: "https://try.gitea.io", + }, + cli.StringFlag{ + EnvVar: "DRONE_GITEA_GIT_USERNAME", + Name: "gitea-git-username", + Usage: "gitea service account username", + }, + cli.StringFlag{ + EnvVar: "DRONE_GITEA_GIT_PASSWORD", + Name: "gitea-git-password", + Usage: "gitea service account password", + }, + cli.BoolFlag{ + EnvVar: "DRONE_GITEA_PRIVATE_MODE", + Name: "gitea-private-mode", + Usage: "gitea private mode enabled", + }, + cli.BoolFlag{ + EnvVar: "DRONE_GITEA_SKIP_VERIFY", + Name: "gitea-skip-verify", + Usage: "gitea skip ssl verification", + }, + cli.BoolFlag{ + EnvVar: "DRONE_BITBUCKET", + Name: "bitbucket", + Usage: "bitbucket driver is enabled", + }, + cli.StringFlag{ + EnvVar: "DRONE_BITBUCKET_CLIENT", + Name: "bitbucket-client", + Usage: "bitbucket oauth2 client id", + }, + cli.StringFlag{ + EnvVar: "DRONE_BITBUCKET_SECRET", + Name: "bitbucket-secret", + Usage: "bitbucket oauth2 client secret", + }, + cli.BoolFlag{ + EnvVar: "DRONE_GITLAB", + Name: "gitlab", + Usage: "gitlab driver is enabled", + }, + cli.StringFlag{ + EnvVar: "DRONE_GITLAB_URL", + Name: "gitlab-server", + Usage: "gitlab server address", + Value: "https://gitlab.com", + }, + cli.StringFlag{ + EnvVar: "DRONE_GITLAB_CLIENT", + Name: "gitlab-client", + Usage: "gitlab oauth2 client id", + }, + cli.StringFlag{ + EnvVar: "DRONE_GITLAB_SECRET", + Name: "gitlab-secret", + Usage: "gitlab oauth2 client secret", + }, + cli.StringFlag{ + EnvVar: "DRONE_GITLAB_GIT_USERNAME", + Name: "gitlab-git-username", + Usage: "gitlab service account username", + }, + cli.StringFlag{ + EnvVar: "DRONE_GITLAB_GIT_PASSWORD", + Name: "gitlab-git-password", + Usage: "gitlab service account password", + }, + cli.BoolFlag{ + EnvVar: "DRONE_GITLAB_SKIP_VERIFY", + Name: "gitlab-skip-verify", + Usage: "gitlab skip ssl verification", + }, + cli.BoolFlag{ + EnvVar: "DRONE_GITLAB_PRIVATE_MODE", + Name: "gitlab-private-mode", + Usage: "gitlab is running in private mode", + }, + cli.BoolFlag{ + EnvVar: "DRONE_STASH", + Name: "stash", + Usage: "stash driver is enabled", + }, + cli.StringFlag{ + EnvVar: "DRONE_STASH_URL", + Name: "stash-server", + Usage: "stash server address", + }, + cli.StringFlag{ + EnvVar: "DRONE_STASH_CONSUMER_KEY", + Name: "stash-consumer-key", + Usage: "stash oauth1 consumer key", + }, + cli.StringFlag{ + EnvVar: "DRONE_STASH_CONSUMER_RSA", + Name: "stash-consumer-rsa", + Usage: "stash oauth1 private key file", + }, + cli.StringFlag{ + EnvVar: "DRONE_STASH_CONSUMER_RSA_STRING", + Name: "stash-consumer-rsa-string", + Usage: "stash oauth1 private key string", + }, + cli.StringFlag{ + EnvVar: "DRONE_STASH_GIT_USERNAME", + Name: "stash-git-username", + Usage: "stash service account username", + }, + cli.StringFlag{ + EnvVar: "DRONE_STASH_GIT_PASSWORD", + Name: "stash-git-password", + Usage: "stash service account password", + }, + cli.BoolFlag{ + EnvVar: "DRONE_STASH_SKIP_VERIFY", + Name: "stash-skip-verify", + Usage: "stash skip ssl verification", + }, +} + +func server(c *cli.Context) error { + + // debug level if requested by user + if c.Bool("debug") { + logrus.SetLevel(logrus.DebugLevel) + } else { + logrus.SetLevel(logrus.WarnLevel) + } + + remote_, err := SetupRemote(c) + if err != nil { + logrus.Fatal(err) + } + + store_ := setupStore(c) + setupEvilGlobals(c, store_, remote_) + + // setup the server and start the listener + handler := router.Load( + ginrus.Ginrus(logrus.StandardLogger(), time.RFC3339, true), + middleware.Version, + middleware.Config(c), + middleware.Cache(c), + middleware.Store(c, store_), + middleware.Remote(remote_), + ) + + var g errgroup.Group + + // start the grpc server + g.Go(func() error { + + lis, err := net.Listen("tcp", ":9000") + if err != nil { + logrus.Error(err) + return err + } + s := grpc.NewServer() + ss := new(droneserver.DroneServer) + ss.Queue = droneserver.Config.Services.Queue + ss.Logger = droneserver.Config.Services.Logs + ss.Pubsub = droneserver.Config.Services.Pubsub + ss.Remote = remote_ + ss.Store = store_ + ss.Host = droneserver.Config.Server.Host + proto.RegisterDroneServer(s, ss) + + err = s.Serve(lis) + if err != nil { + logrus.Error(err) + return err + } + return nil + }) + + // start the server with tls enabled + if c.String("server-cert") != "" { + return http.ListenAndServeTLS( + c.String("server-addr"), + c.String("server-cert"), + c.String("server-key"), + handler, + ) + } + + // start the server without tls enabled + if !c.Bool("lets-encrypt") { + return http.ListenAndServe( + c.String("server-addr"), + handler, + ) + } + + // start the server with lets encrypt enabled + // listen on ports 443 and 80 + g.Go(func() error { + return http.ListenAndServe(":http", handler) + }) + + g.Go(func() error { + address, err := url.Parse(c.String("server-host")) + if err != nil { + return err + } + return http.Serve(autocert.NewListener(address.Host), handler) + }) + + return g.Wait() +} + +// HACK please excuse the message during this period of heavy refactoring. +// We are currently transitioning from storing services (ie database, queue) +// in the gin.Context to storing them in a struct. We are also moving away +// from gin to gorilla. We will temporarily use global during our refactoring +// which will be removing in the final implementation. +func setupEvilGlobals(c *cli.Context, v store.Store, r remote.Remote) { + + // storage + droneserver.Config.Storage.Files = v + droneserver.Config.Storage.Config = v + + // services + droneserver.Config.Services.Queue = setupQueue(c, v) + droneserver.Config.Services.Logs = logging.New() + droneserver.Config.Services.Pubsub = pubsub.New() + droneserver.Config.Services.Pubsub.Create(context.Background(), "topic/events") + droneserver.Config.Services.Registries = setupRegistryService(c, v) + droneserver.Config.Services.Secrets = setupSecretService(c, v) + droneserver.Config.Services.Senders = sender.New(v, v) + droneserver.Config.Services.Environ = setupEnvironService(c, v) + + if endpoint := c.String("registry-service"); endpoint != "" { + droneserver.Config.Services.Registries = registry.NewRemote(endpoint) + } + if endpoint := c.String("secret-service"); endpoint != "" { + droneserver.Config.Services.Secrets = secrets.NewRemote(endpoint) + } + if endpoint := c.String("gating-service"); endpoint != "" { + droneserver.Config.Services.Senders = sender.NewRemote(endpoint) + } + + // limits + droneserver.Config.Pipeline.Limits.MemSwapLimit = c.Int64("limit-mem-swap") + droneserver.Config.Pipeline.Limits.MemLimit = c.Int64("limit-mem") + droneserver.Config.Pipeline.Limits.ShmSize = c.Int64("limit-shm-size") + droneserver.Config.Pipeline.Limits.CPUQuota = c.Int64("limit-cpu-quota") + droneserver.Config.Pipeline.Limits.CPUShares = c.Int64("limit-cpu-shares") + droneserver.Config.Pipeline.Limits.CPUSet = c.String("limit-cpu-set") + + // server configuration + droneserver.Config.Server.Cert = c.String("server-cert") + droneserver.Config.Server.Key = c.String("server-key") + droneserver.Config.Server.Pass = c.String("agent-secret") + droneserver.Config.Server.Host = strings.TrimRight(c.String("server-host"), "/") + droneserver.Config.Server.Port = c.String("server-addr") + droneserver.Config.Pipeline.Networks = c.StringSlice("network") + droneserver.Config.Pipeline.Volumes = c.StringSlice("volume") + droneserver.Config.Pipeline.Privileged = c.StringSlice("escalate") + // droneserver.Config.Server.Open = cli.Bool("open") + // droneserver.Config.Server.Orgs = sliceToMap(cli.StringSlice("orgs")) + // droneserver.Config.Server.Admins = sliceToMap(cli.StringSlice("admin")) +} diff --git a/drone/server/setup.go b/cmd/drone-server/setup.go similarity index 93% rename from drone/server/setup.go rename to cmd/drone-server/setup.go index 8c53f2457..e76afbc13 100644 --- a/drone/server/setup.go +++ b/cmd/drone-server/setup.go @@ -1,6 +1,4 @@ -// +build !enterprise - -package server +package main import ( "fmt" @@ -41,12 +39,16 @@ func setupRegistryService(c *cli.Context, s store.Store) model.RegistryService { return registry.New(s) } +func setupEnvironService(c *cli.Context, s store.Store) model.EnvironService { + return nil +} + func setupPubsub(c *cli.Context) {} -func setupStream(c *cli.Command) {} -func setupGatingService(c *cli.Command) {} +func setupStream(c *cli.Context) {} +func setupGatingService(c *cli.Context) {} // helper function to setup the remote from the CLI arguments. -func setupRemote(c *cli.Context) (remote.Remote, error) { +func SetupRemote(c *cli.Context) (remote.Remote, error) { switch { case c.Bool("github"): return setupGithub(c) @@ -136,3 +138,5 @@ func setupGithub(c *cli.Context) (remote.Remote, error) { MergeRef: c.BoolT("github-merge-ref"), }) } + +func before(c *cli.Context) error { return nil } diff --git a/drone/main.go b/drone/main.go deleted file mode 100644 index ba158a697..000000000 --- a/drone/main.go +++ /dev/null @@ -1,46 +0,0 @@ -// +build !extras - -package main - -import ( - "fmt" - "os" - - "github.com/drone/drone/drone/agent" - "github.com/drone/drone/drone/server" - "github.com/drone/drone/version" - - "github.com/ianschenck/envflag" - _ "github.com/joho/godotenv/autoload" - "github.com/urfave/cli" -) - -func main() { - envflag.Parse() - - app := cli.NewApp() - app.Name = "drone" - app.Version = version.Version.String() - app.Usage = "command line utility" - app.Flags = []cli.Flag{ - cli.StringFlag{ - Name: "t, token", - Usage: "server auth token", - EnvVar: "DRONE_TOKEN", - }, - cli.StringFlag{ - Name: "s, server", - Usage: "server location", - EnvVar: "DRONE_SERVER", - }, - } - app.Commands = []cli.Command{ - agent.Command, - server.Command, - } - - if err := app.Run(os.Args); err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(1) - } -} diff --git a/drone/main_extras.go b/drone/main_extras.go deleted file mode 100644 index 23fb9b4ae..000000000 --- a/drone/main_extras.go +++ /dev/null @@ -1,47 +0,0 @@ -// +build extras - -package main - -import ( - "fmt" - "os" - - "github.com/drone/drone/drone/agent" - "github.com/drone/drone/version" - - "github.com/drone/drone/extras/cmd/drone/server" - - "github.com/ianschenck/envflag" - _ "github.com/joho/godotenv/autoload" - "github.com/urfave/cli" -) - -func main() { - envflag.Parse() - - app := cli.NewApp() - app.Name = "drone" - app.Version = version.Version.String() - app.Usage = "command line utility" - app.Flags = []cli.Flag{ - cli.StringFlag{ - Name: "t, token", - Usage: "server auth token", - EnvVar: "DRONE_TOKEN", - }, - cli.StringFlag{ - Name: "s, server", - Usage: "server location", - EnvVar: "DRONE_SERVER", - }, - } - app.Commands = []cli.Command{ - agent.Command, - server.Command, - } - - if err := app.Run(os.Args); err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(1) - } -} diff --git a/drone/server/server.go b/drone/server/server.go deleted file mode 100644 index 9f2366123..000000000 --- a/drone/server/server.go +++ /dev/null @@ -1,534 +0,0 @@ -package server - -import ( - "context" - "net" - "net/http" - "net/url" - "strings" - "time" - - "google.golang.org/grpc" - - "golang.org/x/crypto/acme/autocert" - "golang.org/x/sync/errgroup" - - "github.com/cncd/logging" - "github.com/cncd/pipeline/pipeline/rpc/proto" - "github.com/cncd/pubsub" - "github.com/drone/drone/plugins/registry" - "github.com/drone/drone/plugins/secrets" - "github.com/drone/drone/plugins/sender" - "github.com/drone/drone/remote" - "github.com/drone/drone/router" - "github.com/drone/drone/router/middleware" - droneserver "github.com/drone/drone/server" - "github.com/drone/drone/store" - - "github.com/Sirupsen/logrus" - "github.com/gin-gonic/contrib/ginrus" - "github.com/urfave/cli" -) - -// Command exports the server command. -var Command = cli.Command{ - Name: "server", - Usage: "starts the drone server daemon", - Action: server, - Flags: []cli.Flag{ - cli.BoolFlag{ - EnvVar: "DRONE_DEBUG", - Name: "debug", - Usage: "start the server in debug mode", - }, - cli.StringFlag{ - EnvVar: "DRONE_SERVER_HOST,DRONE_HOST", - Name: "server-host", - Usage: "server host", - }, - cli.StringFlag{ - EnvVar: "DRONE_SERVER_ADDR", - Name: "server-addr", - Usage: "server address", - Value: ":8000", - }, - cli.StringFlag{ - EnvVar: "DRONE_SERVER_CERT", - Name: "server-cert", - Usage: "server ssl cert", - }, - cli.StringFlag{ - EnvVar: "DRONE_SERVER_KEY", - Name: "server-key", - Usage: "server ssl key", - }, - cli.BoolFlag{ - EnvVar: "DRONE_LETS_ENCRYPT", - Name: "lets-encrypt", - Usage: "lets encrypt enabled", - }, - cli.StringSliceFlag{ - EnvVar: "DRONE_ADMIN", - Name: "admin", - Usage: "list of admin users", - }, - cli.StringSliceFlag{ - EnvVar: "DRONE_ORGS", - Name: "orgs", - Usage: "list of approved organizations", - }, - cli.BoolFlag{ - EnvVar: "DRONE_OPEN", - Name: "open", - Usage: "open user registration", - }, - cli.DurationFlag{ - EnvVar: "DRONE_CACHE_TTL", - Name: "cache-ttl", - Usage: "cache duration", - Value: time.Minute * 15, - }, - cli.StringSliceFlag{ - EnvVar: "DRONE_ESCALATE", - Name: "escalate", - Value: &cli.StringSlice{ - "plugins/docker", - "plugins/gcr", - "plugins/ecr", - }, - }, - cli.StringSliceFlag{ - EnvVar: "DRONE_VOLUME", - Name: "volume", - }, - cli.StringSliceFlag{ - EnvVar: "DRONE_NETWORK", - Name: "network", - }, - cli.StringFlag{ - EnvVar: "DRONE_AGENT_SECRET,DRONE_SECRET", - Name: "agent-secret", - Usage: "agent secret passcode", - }, - cli.StringFlag{ - EnvVar: "DRONE_SECRET_ENDPOINT", - Name: "secret-service", - Usage: "secret plugin endpoint", - }, - cli.StringFlag{ - EnvVar: "DRONE_REGISTRY_ENDPOINT", - Name: "registry-service", - Usage: "registry plugin endpoint", - }, - cli.StringFlag{ - EnvVar: "DRONE_GATEKEEPER_ENDPOINT", - Name: "gating-service", - Usage: "gated build endpoint", - }, - cli.StringFlag{ - EnvVar: "DRONE_DATABASE_DRIVER,DATABASE_DRIVER", - Name: "driver", - Usage: "database driver", - Value: "sqlite3", - }, - cli.StringFlag{ - EnvVar: "DRONE_DATABASE_DATASOURCE,DATABASE_CONFIG", - Name: "datasource", - Usage: "database driver configuration string", - Value: "drone.sqlite", - }, - // - // resource limit parameters - // - cli.Int64Flag{ - Name: "limit-mem-swap", - EnvVar: "DRONE_LIMIT_MEM_SWAP", - }, - cli.Int64Flag{ - Name: "limit-mem", - EnvVar: "DRONE_LIMIT_MEM", - }, - cli.Int64Flag{ - Name: "limit-shm-size", - EnvVar: "DRONE_LIMIT_SHM_SIZE", - }, - cli.Int64Flag{ - Name: "limit-cpu-quota", - EnvVar: "DRONE_LIMIT_CPU_QUOTA", - }, - cli.Int64Flag{ - Name: "limit-cpu-shares", - EnvVar: "DRONE_LIMIT_CPU_SHARES", - }, - cli.StringFlag{ - Name: "limit-cpu-set", - EnvVar: "DRONE_LIMIT_CPU_SET", - }, - // - // remote parameters - // - cli.BoolFlag{ - EnvVar: "DRONE_GITHUB", - Name: "github", - Usage: "github driver is enabled", - }, - cli.StringFlag{ - EnvVar: "DRONE_GITHUB_URL", - Name: "github-server", - Usage: "github server address", - Value: "https://github.com", - }, - cli.StringFlag{ - EnvVar: "DRONE_GITHUB_CONTEXT", - Name: "github-context", - Usage: "github status context", - Value: "continuous-integration/drone", - }, - cli.StringFlag{ - EnvVar: "DRONE_GITHUB_CLIENT", - Name: "github-client", - Usage: "github oauth2 client id", - }, - cli.StringFlag{ - EnvVar: "DRONE_GITHUB_SECRET", - Name: "github-secret", - Usage: "github oauth2 client secret", - }, - cli.StringSliceFlag{ - EnvVar: "DRONE_GITHUB_SCOPE", - Name: "github-scope", - Usage: "github oauth scope", - Value: &cli.StringSlice{ - "repo", - "repo:status", - "user:email", - "read:org", - }, - }, - cli.StringFlag{ - EnvVar: "DRONE_GITHUB_GIT_USERNAME", - Name: "github-git-username", - Usage: "github machine user username", - }, - cli.StringFlag{ - EnvVar: "DRONE_GITHUB_GIT_PASSWORD", - Name: "github-git-password", - Usage: "github machine user password", - }, - cli.BoolTFlag{ - EnvVar: "DRONE_GITHUB_MERGE_REF", - Name: "github-merge-ref", - Usage: "github pull requests use merge ref", - }, - cli.BoolFlag{ - EnvVar: "DRONE_GITHUB_PRIVATE_MODE", - Name: "github-private-mode", - Usage: "github is running in private mode", - }, - cli.BoolFlag{ - EnvVar: "DRONE_GITHUB_SKIP_VERIFY", - Name: "github-skip-verify", - Usage: "github skip ssl verification", - }, - cli.BoolFlag{ - EnvVar: "DRONE_GOGS", - Name: "gogs", - Usage: "gogs driver is enabled", - }, - cli.StringFlag{ - EnvVar: "DRONE_GOGS_URL", - Name: "gogs-server", - Usage: "gogs server address", - Value: "https://github.com", - }, - cli.StringFlag{ - EnvVar: "DRONE_GOGS_GIT_USERNAME", - Name: "gogs-git-username", - Usage: "gogs service account username", - }, - cli.StringFlag{ - EnvVar: "DRONE_GOGS_GIT_PASSWORD", - Name: "gogs-git-password", - Usage: "gogs service account password", - }, - cli.BoolFlag{ - EnvVar: "DRONE_GOGS_PRIVATE_MODE", - Name: "gogs-private-mode", - Usage: "gogs private mode enabled", - }, - cli.BoolFlag{ - EnvVar: "DRONE_GOGS_SKIP_VERIFY", - Name: "gogs-skip-verify", - Usage: "gogs skip ssl verification", - }, - cli.BoolFlag{ - EnvVar: "DRONE_GITEA", - Name: "gitea", - Usage: "gitea driver is enabled", - }, - cli.StringFlag{ - EnvVar: "DRONE_GITEA_URL", - Name: "gitea-server", - Usage: "gitea server address", - Value: "https://try.gitea.io", - }, - cli.StringFlag{ - EnvVar: "DRONE_GITEA_GIT_USERNAME", - Name: "gitea-git-username", - Usage: "gitea service account username", - }, - cli.StringFlag{ - EnvVar: "DRONE_GITEA_GIT_PASSWORD", - Name: "gitea-git-password", - Usage: "gitea service account password", - }, - cli.BoolFlag{ - EnvVar: "DRONE_GITEA_PRIVATE_MODE", - Name: "gitea-private-mode", - Usage: "gitea private mode enabled", - }, - cli.BoolFlag{ - EnvVar: "DRONE_GITEA_SKIP_VERIFY", - Name: "gitea-skip-verify", - Usage: "gitea skip ssl verification", - }, - cli.BoolFlag{ - EnvVar: "DRONE_BITBUCKET", - Name: "bitbucket", - Usage: "bitbucket driver is enabled", - }, - cli.StringFlag{ - EnvVar: "DRONE_BITBUCKET_CLIENT", - Name: "bitbucket-client", - Usage: "bitbucket oauth2 client id", - }, - cli.StringFlag{ - EnvVar: "DRONE_BITBUCKET_SECRET", - Name: "bitbucket-secret", - Usage: "bitbucket oauth2 client secret", - }, - cli.BoolFlag{ - EnvVar: "DRONE_GITLAB", - Name: "gitlab", - Usage: "gitlab driver is enabled", - }, - cli.StringFlag{ - EnvVar: "DRONE_GITLAB_URL", - Name: "gitlab-server", - Usage: "gitlab server address", - Value: "https://gitlab.com", - }, - cli.StringFlag{ - EnvVar: "DRONE_GITLAB_CLIENT", - Name: "gitlab-client", - Usage: "gitlab oauth2 client id", - }, - cli.StringFlag{ - EnvVar: "DRONE_GITLAB_SECRET", - Name: "gitlab-secret", - Usage: "gitlab oauth2 client secret", - }, - cli.StringFlag{ - EnvVar: "DRONE_GITLAB_GIT_USERNAME", - Name: "gitlab-git-username", - Usage: "gitlab service account username", - }, - cli.StringFlag{ - EnvVar: "DRONE_GITLAB_GIT_PASSWORD", - Name: "gitlab-git-password", - Usage: "gitlab service account password", - }, - cli.BoolFlag{ - EnvVar: "DRONE_GITLAB_SKIP_VERIFY", - Name: "gitlab-skip-verify", - Usage: "gitlab skip ssl verification", - }, - cli.BoolFlag{ - EnvVar: "DRONE_GITLAB_PRIVATE_MODE", - Name: "gitlab-private-mode", - Usage: "gitlab is running in private mode", - }, - cli.BoolFlag{ - EnvVar: "DRONE_STASH", - Name: "stash", - Usage: "stash driver is enabled", - }, - cli.StringFlag{ - EnvVar: "DRONE_STASH_URL", - Name: "stash-server", - Usage: "stash server address", - }, - cli.StringFlag{ - EnvVar: "DRONE_STASH_CONSUMER_KEY", - Name: "stash-consumer-key", - Usage: "stash oauth1 consumer key", - }, - cli.StringFlag{ - EnvVar: "DRONE_STASH_CONSUMER_RSA", - Name: "stash-consumer-rsa", - Usage: "stash oauth1 private key file", - }, - cli.StringFlag{ - EnvVar: "DRONE_STASH_CONSUMER_RSA_STRING", - Name: "stash-consumer-rsa-string", - Usage: "stash oauth1 private key string", - }, - cli.StringFlag{ - EnvVar: "DRONE_STASH_GIT_USERNAME", - Name: "stash-git-username", - Usage: "stash service account username", - }, - cli.StringFlag{ - EnvVar: "DRONE_STASH_GIT_PASSWORD", - Name: "stash-git-password", - Usage: "stash service account password", - }, - cli.BoolFlag{ - EnvVar: "DRONE_STASH_SKIP_VERIFY", - Name: "stash-skip-verify", - Usage: "stash skip ssl verification", - }, - }, -} - -func server(c *cli.Context) error { - - // debug level if requested by user - if c.Bool("debug") { - logrus.SetLevel(logrus.DebugLevel) - } else { - logrus.SetLevel(logrus.WarnLevel) - } - - remote_, err := setupRemote(c) - if err != nil { - logrus.Fatal(err) - } - - store_ := setupStore(c) - setupEvilGlobals(c, store_, remote_) - - // setup the server and start the listener - handler := router.Load( - ginrus.Ginrus(logrus.StandardLogger(), time.RFC3339, true), - middleware.Version, - middleware.Config(c), - middleware.Cache(c), - middleware.Store(c, store_), - middleware.Remote(remote_), - ) - - var g errgroup.Group - - // start the grpc server - g.Go(func() error { - - lis, err := net.Listen("tcp", ":9000") - if err != nil { - logrus.Error(err) - return err - } - s := grpc.NewServer() - ss := new(droneserver.DroneServer) - ss.Queue = droneserver.Config.Services.Queue - ss.Logger = droneserver.Config.Services.Logs - ss.Pubsub = droneserver.Config.Services.Pubsub - ss.Remote = remote_ - ss.Store = store_ - ss.Host = droneserver.Config.Server.Host - proto.RegisterDroneServer(s, ss) - - err = s.Serve(lis) - if err != nil { - logrus.Error(err) - return err - } - return nil - }) - - // start the server with tls enabled - if c.String("server-cert") != "" { - return http.ListenAndServeTLS( - c.String("server-addr"), - c.String("server-cert"), - c.String("server-key"), - handler, - ) - } - - // start the server without tls enabled - if !c.Bool("lets-encrypt") { - return http.ListenAndServe( - c.String("server-addr"), - handler, - ) - } - - // start the server with lets encrypt enabled - // listen on ports 443 and 80 - g.Go(func() error { - return http.ListenAndServe(":http", handler) - }) - - g.Go(func() error { - address, err := url.Parse(c.String("server-host")) - if err != nil { - return err - } - return http.Serve(autocert.NewListener(address.Host), handler) - }) - - return g.Wait() -} - -// HACK please excuse the message during this period of heavy refactoring. -// We are currently transitioning from storing services (ie database, queue) -// in the gin.Context to storing them in a struct. We are also moving away -// from gin to gorilla. We will temporarily use global during our refactoring -// which will be removing in the final implementation. -func setupEvilGlobals(c *cli.Context, v store.Store, r remote.Remote) { - - // storage - droneserver.Config.Storage.Files = v - droneserver.Config.Storage.Config = v - - // services - droneserver.Config.Services.Queue = setupQueue(c, v) - droneserver.Config.Services.Logs = logging.New() - droneserver.Config.Services.Pubsub = pubsub.New() - droneserver.Config.Services.Pubsub.Create(context.Background(), "topic/events") - droneserver.Config.Services.Registries = setupRegistryService(c, v) - droneserver.Config.Services.Secrets = setupSecretService(c, v) - droneserver.Config.Services.Senders = sender.New(v, v) - - if endpoint := c.String("registry-service"); endpoint != "" { - droneserver.Config.Services.Registries = registry.NewRemote(endpoint) - } - if endpoint := c.String("secret-service"); endpoint != "" { - droneserver.Config.Services.Secrets = secrets.NewRemote(endpoint) - } - if endpoint := c.String("gating-service"); endpoint != "" { - droneserver.Config.Services.Senders = sender.NewRemote(endpoint) - } - - // limits - droneserver.Config.Pipeline.Limits.MemSwapLimit = c.Int64("limit-mem-swap") - droneserver.Config.Pipeline.Limits.MemLimit = c.Int64("limit-mem") - droneserver.Config.Pipeline.Limits.ShmSize = c.Int64("limit-shm-size") - droneserver.Config.Pipeline.Limits.CPUQuota = c.Int64("limit-cpu-quota") - droneserver.Config.Pipeline.Limits.CPUShares = c.Int64("limit-cpu-shares") - droneserver.Config.Pipeline.Limits.CPUSet = c.String("limit-cpu-set") - - // server configuration - droneserver.Config.Server.Cert = c.String("server-cert") - droneserver.Config.Server.Key = c.String("server-key") - droneserver.Config.Server.Pass = c.String("agent-secret") - droneserver.Config.Server.Host = strings.TrimRight(c.String("server-host"), "/") - droneserver.Config.Server.Port = c.String("server-addr") - droneserver.Config.Pipeline.Networks = c.StringSlice("network") - droneserver.Config.Pipeline.Volumes = c.StringSlice("volume") - droneserver.Config.Pipeline.Privileged = c.StringSlice("escalate") - // droneserver.Config.Server.Open = cli.Bool("open") - // droneserver.Config.Server.Orgs = sliceToMap(cli.StringSlice("orgs")) - // droneserver.Config.Server.Admins = sliceToMap(cli.StringSlice("admin")) -}