separate agent and server binary

This commit is contained in:
Brad Rydzewski 2017-06-29 18:51:22 -04:00
parent a27b21909c
commit 1a6920e822
18 changed files with 650 additions and 1387 deletions

View file

@ -22,4 +22,5 @@ set -x
git clone git@github.com:drone/drone-enterprise.git extras git clone git@github.com:drone/drone-enterprise.git extras
# build a static binary with the build number and extra features. # 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

View file

@ -37,7 +37,7 @@ pipeline:
when: when:
event: [ push, tag ] event: [ push, tag ]
publish: publish_server:
image: plugins/docker image: plugins/docker
repo: drone/drone repo: drone/drone
secrets: [ docker_username, docker_password ] secrets: [ docker_username, docker_password ]
@ -46,7 +46,17 @@ pipeline:
branch: master branch: master
event: push 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 image: plugins/docker
repo: drone/drone repo: drone/drone
secrets: [ docker_username, docker_password ] secrets: [ docker_username, docker_password ]
@ -54,6 +64,15 @@ pipeline:
when: when:
event: tag 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: notify:
image: plugins/gitter image: plugins/gitter
secrets: [ gitter_webhook ] secrets: [ gitter_webhook ]

View file

@ -8,7 +8,6 @@ ENV DATABASE_CONFIG=/var/lib/drone/drone.sqlite
ENV GODEBUG=netdns=go ENV GODEBUG=netdns=go
ENV XDG_CACHE_HOME /var/lib/drone ENV XDG_CACHE_HOME /var/lib/drone
ADD release/drone /drone ADD release/drone-server /bin/
ENTRYPOINT ["/drone"] ENTRYPOINT ["/bin/drone-server"]
CMD ["server"]

7
Dockerfile.agent Normal file
View file

@ -0,0 +1,7 @@
# docker build --rm -t drone/drone .
FROM centurylink/ca-certs
ADD release/drone-agent /bin/
ENTRYPOINT ["/bin/drone-agent"]

View file

@ -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"]

View file

@ -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"]

View file

@ -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"]

View file

@ -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
}

View file

@ -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
}

View file

@ -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
}

View file

@ -1,4 +1,4 @@
package agent package main
import ( import (
"context" "context"
@ -23,41 +23,6 @@ import (
"github.com/urfave/cli" "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 { func loop(c *cli.Context) error {
// endpoint, err := url.Parse( // endpoint, err := url.Parse(
// c.String("drone-server"), // c.String("drone-server"),

52
cmd/drone-agent/main.go Normal file
View file

@ -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)
}
}

26
cmd/drone-server/main.go Normal file
View file

@ -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)
}
}

529
cmd/drone-server/server.go Normal file
View file

@ -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"))
}

View file

@ -1,6 +1,4 @@
// +build !enterprise package main
package server
import ( import (
"fmt" "fmt"
@ -41,12 +39,16 @@ func setupRegistryService(c *cli.Context, s store.Store) model.RegistryService {
return registry.New(s) return registry.New(s)
} }
func setupEnvironService(c *cli.Context, s store.Store) model.EnvironService {
return nil
}
func setupPubsub(c *cli.Context) {} func setupPubsub(c *cli.Context) {}
func setupStream(c *cli.Command) {} func setupStream(c *cli.Context) {}
func setupGatingService(c *cli.Command) {} func setupGatingService(c *cli.Context) {}
// helper function to setup the remote from the CLI arguments. // 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 { switch {
case c.Bool("github"): case c.Bool("github"):
return setupGithub(c) return setupGithub(c)
@ -136,3 +138,5 @@ func setupGithub(c *cli.Context) (remote.Remote, error) {
MergeRef: c.BoolT("github-merge-ref"), MergeRef: c.BoolT("github-merge-ref"),
}) })
} }
func before(c *cli.Context) error { return nil }

View file

@ -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)
}
}

View file

@ -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)
}
}

View file

@ -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"))
}