2016-04-20 01:37:53 +00:00
|
|
|
package agent
|
|
|
|
|
|
|
|
import (
|
2016-07-18 07:06:34 +00:00
|
|
|
"os"
|
|
|
|
"os/signal"
|
2016-04-20 01:37:53 +00:00
|
|
|
"sync"
|
2016-07-18 07:06:34 +00:00
|
|
|
"syscall"
|
2016-04-20 01:37:53 +00:00
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/drone/drone/client"
|
2016-05-24 01:47:44 +00:00
|
|
|
"github.com/drone/drone/shared/token"
|
2016-04-20 01:37:53 +00:00
|
|
|
"github.com/samalba/dockerclient"
|
|
|
|
|
|
|
|
"github.com/Sirupsen/logrus"
|
|
|
|
"github.com/codegangsta/cli"
|
2016-08-13 00:04:42 +00:00
|
|
|
"strings"
|
2016-04-20 01:37:53 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
// AgentCmd is the exported command for starting the drone agent.
|
|
|
|
var AgentCmd = cli.Command{
|
|
|
|
Name: "agent",
|
|
|
|
Usage: "starts the drone agent",
|
|
|
|
Action: start,
|
|
|
|
Flags: []cli.Flag{
|
|
|
|
cli.StringFlag{
|
|
|
|
EnvVar: "DOCKER_HOST",
|
|
|
|
Name: "docker-host",
|
|
|
|
Usage: "docker deamon address",
|
|
|
|
Value: "unix:///var/run/docker.sock",
|
|
|
|
},
|
|
|
|
cli.BoolFlag{
|
|
|
|
EnvVar: "DOCKER_TLS_VERIFY",
|
|
|
|
Name: "docker-tls-verify",
|
|
|
|
Usage: "docker daemon supports tlsverify",
|
|
|
|
},
|
|
|
|
cli.StringFlag{
|
|
|
|
EnvVar: "DOCKER_CERT_PATH",
|
|
|
|
Name: "docker-cert-path",
|
|
|
|
Usage: "docker certificate directory",
|
|
|
|
Value: "",
|
|
|
|
},
|
|
|
|
cli.IntFlag{
|
|
|
|
EnvVar: "DOCKER_MAX_PROCS",
|
|
|
|
Name: "docker-max-procs",
|
|
|
|
Usage: "limit number of running docker processes",
|
|
|
|
Value: 2,
|
|
|
|
},
|
2016-04-22 00:10:19 +00:00
|
|
|
cli.StringFlag{
|
|
|
|
EnvVar: "DOCKER_OS",
|
|
|
|
Name: "docker-os",
|
|
|
|
Usage: "docker operating system",
|
|
|
|
Value: "linux",
|
|
|
|
},
|
|
|
|
cli.StringFlag{
|
|
|
|
EnvVar: "DOCKER_ARCH",
|
|
|
|
Name: "docker-arch",
|
|
|
|
Usage: "docker architecture system",
|
|
|
|
Value: "amd64",
|
|
|
|
},
|
2016-05-04 06:36:23 +00:00
|
|
|
cli.StringFlag{
|
2016-05-11 05:19:45 +00:00
|
|
|
EnvVar: "DRONE_STORAGE_DRIVER",
|
|
|
|
Name: "drone-storage-driver",
|
2016-05-04 06:36:23 +00:00
|
|
|
Usage: "docker storage driver",
|
|
|
|
Value: "overlay",
|
|
|
|
},
|
2016-04-20 01:37:53 +00:00
|
|
|
cli.StringFlag{
|
|
|
|
EnvVar: "DRONE_SERVER",
|
|
|
|
Name: "drone-server",
|
|
|
|
Usage: "drone server address",
|
|
|
|
Value: "http://localhost:8000",
|
|
|
|
},
|
|
|
|
cli.StringFlag{
|
|
|
|
EnvVar: "DRONE_TOKEN",
|
|
|
|
Name: "drone-token",
|
|
|
|
Usage: "drone authorization token",
|
|
|
|
},
|
2016-05-24 01:47:44 +00:00
|
|
|
cli.StringFlag{
|
|
|
|
EnvVar: "DRONE_SECRET,DRONE_AGENT_SECRET",
|
|
|
|
Name: "drone-secret",
|
|
|
|
Usage: "drone agent secret",
|
|
|
|
},
|
2016-04-20 01:37:53 +00:00
|
|
|
cli.DurationFlag{
|
2016-04-21 08:18:20 +00:00
|
|
|
EnvVar: "DRONE_BACKOFF",
|
|
|
|
Name: "backoff",
|
2016-04-20 01:37:53 +00:00
|
|
|
Usage: "drone server backoff interval",
|
|
|
|
Value: time.Second * 15,
|
|
|
|
},
|
2016-05-11 21:37:56 +00:00
|
|
|
cli.DurationFlag{
|
|
|
|
EnvVar: "DRONE_PING",
|
|
|
|
Name: "ping",
|
|
|
|
Usage: "drone server ping frequency",
|
|
|
|
Value: time.Minute * 5,
|
|
|
|
},
|
2016-04-20 01:37:53 +00:00
|
|
|
cli.BoolFlag{
|
2016-04-21 08:18:20 +00:00
|
|
|
EnvVar: "DRONE_DEBUG",
|
2016-04-20 01:37:53 +00:00
|
|
|
Name: "debug",
|
|
|
|
Usage: "start the agent in debug mode",
|
|
|
|
},
|
2016-05-12 20:24:51 +00:00
|
|
|
cli.DurationFlag{
|
|
|
|
EnvVar: "DRONE_TIMEOUT",
|
|
|
|
Name: "timeout",
|
|
|
|
Usage: "drone timeout due to log inactivity",
|
|
|
|
Value: time.Minute * 5,
|
|
|
|
},
|
|
|
|
cli.IntFlag{
|
|
|
|
EnvVar: "DRONE_MAX_LOGS",
|
|
|
|
Name: "max-log-size",
|
|
|
|
Usage: "drone maximum log size in megabytes",
|
|
|
|
Value: 5,
|
|
|
|
},
|
2016-04-21 08:18:20 +00:00
|
|
|
cli.StringSliceFlag{
|
2016-04-22 00:10:19 +00:00
|
|
|
EnvVar: "DRONE_PLUGIN_PRIVILEGED",
|
|
|
|
Name: "privileged",
|
2016-04-21 08:18:20 +00:00
|
|
|
Usage: "plugins that require privileged mode",
|
2016-04-22 00:10:19 +00:00
|
|
|
Value: &cli.StringSlice{
|
|
|
|
"plugins/docker",
|
|
|
|
"plugins/docker:*",
|
2016-05-02 17:22:04 +00:00
|
|
|
"plugins/gcr",
|
|
|
|
"plugins/gcr:*",
|
2016-04-22 00:10:19 +00:00
|
|
|
"plugins/ecr",
|
|
|
|
"plugins/ecr:*",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
cli.StringFlag{
|
|
|
|
EnvVar: "DRONE_PLUGIN_NAMESPACE",
|
|
|
|
Name: "namespace",
|
|
|
|
Value: "plugins",
|
|
|
|
Usage: "default plugin image namespace",
|
|
|
|
},
|
2016-05-13 05:14:33 +00:00
|
|
|
cli.BoolTFlag{
|
2016-05-11 05:19:45 +00:00
|
|
|
EnvVar: "DRONE_PLUGIN_PULL",
|
|
|
|
Name: "pull",
|
|
|
|
Usage: "always pull latest plugin images",
|
2016-04-21 08:18:20 +00:00
|
|
|
},
|
2016-04-20 01:37:53 +00:00
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
func start(c *cli.Context) {
|
|
|
|
|
|
|
|
// debug level if requested by user
|
|
|
|
if c.Bool("debug") {
|
|
|
|
logrus.SetLevel(logrus.DebugLevel)
|
|
|
|
} else {
|
|
|
|
logrus.SetLevel(logrus.WarnLevel)
|
|
|
|
}
|
2016-05-24 01:47:44 +00:00
|
|
|
|
|
|
|
var accessToken string
|
|
|
|
if c.String("drone-secret") != "" {
|
|
|
|
secretToken := c.String("drone-secret")
|
|
|
|
accessToken, _ = token.New(token.AgentToken, "").Sign(secretToken)
|
|
|
|
} else {
|
|
|
|
accessToken = c.String("drone-token")
|
|
|
|
}
|
|
|
|
|
2016-05-11 00:03:24 +00:00
|
|
|
logrus.Infof("Connecting to %s with token %s",
|
|
|
|
c.String("drone-server"),
|
2016-05-24 01:47:44 +00:00
|
|
|
accessToken,
|
2016-05-11 00:03:24 +00:00
|
|
|
)
|
2016-04-20 01:37:53 +00:00
|
|
|
|
|
|
|
client := client.NewClientToken(
|
2016-08-13 00:04:42 +00:00
|
|
|
strings.TrimRight(c.String("drone-server"),"/"),
|
2016-05-24 01:47:44 +00:00
|
|
|
accessToken,
|
2016-04-20 01:37:53 +00:00
|
|
|
)
|
|
|
|
|
2016-04-29 19:39:56 +00:00
|
|
|
tls, err := dockerclient.TLSConfigFromCertPath(c.String("docker-cert-path"))
|
|
|
|
if err == nil {
|
|
|
|
tls.InsecureSkipVerify = c.Bool("docker-tls-verify")
|
2016-04-20 01:37:53 +00:00
|
|
|
}
|
|
|
|
docker, err := dockerclient.NewDockerClient(c.String("docker-host"), tls)
|
|
|
|
if err != nil {
|
|
|
|
logrus.Fatal(err)
|
|
|
|
}
|
|
|
|
|
2016-05-11 21:37:56 +00:00
|
|
|
go func() {
|
|
|
|
for {
|
|
|
|
if err := client.Ping(); err != nil {
|
|
|
|
logrus.Warnf("unable to ping the server. %s", err.Error())
|
|
|
|
}
|
|
|
|
time.Sleep(c.Duration("ping"))
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
|
2016-04-20 01:37:53 +00:00
|
|
|
var wg sync.WaitGroup
|
|
|
|
for i := 0; i < c.Int("docker-max-procs"); i++ {
|
|
|
|
wg.Add(1)
|
|
|
|
go func() {
|
2016-04-22 00:10:19 +00:00
|
|
|
r := pipeline{
|
|
|
|
drone: client,
|
|
|
|
docker: docker,
|
|
|
|
config: config{
|
2016-05-13 16:56:58 +00:00
|
|
|
platform: c.String("docker-os") + "/" + c.String("docker-arch"),
|
2016-05-12 20:24:51 +00:00
|
|
|
timeout: c.Duration("timeout"),
|
2016-04-22 00:10:19 +00:00
|
|
|
namespace: c.String("namespace"),
|
|
|
|
privileged: c.StringSlice("privileged"),
|
2016-05-13 05:14:33 +00:00
|
|
|
pull: c.BoolT("pull"),
|
2016-05-12 20:24:51 +00:00
|
|
|
logs: int64(c.Int("max-log-size")) * 1000000,
|
2016-04-22 00:10:19 +00:00
|
|
|
},
|
|
|
|
}
|
2016-04-20 01:37:53 +00:00
|
|
|
for {
|
2016-04-22 00:10:19 +00:00
|
|
|
if err := r.run(); err != nil {
|
2016-04-21 08:18:20 +00:00
|
|
|
dur := c.Duration("backoff")
|
2016-05-03 00:47:58 +00:00
|
|
|
logrus.Warnf("reconnect in %v. %s", dur, err.Error())
|
2016-04-20 01:37:53 +00:00
|
|
|
time.Sleep(dur)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
}
|
2016-07-18 07:06:34 +00:00
|
|
|
handleSignals()
|
2016-04-20 01:37:53 +00:00
|
|
|
wg.Wait()
|
|
|
|
}
|
2016-07-18 07:06:34 +00:00
|
|
|
|
|
|
|
// tracks running builds
|
|
|
|
var running sync.WaitGroup
|
|
|
|
|
|
|
|
func handleSignals() {
|
|
|
|
// Graceful shut-down on SIGINT/SIGTERM
|
|
|
|
c := make(chan os.Signal, 1)
|
|
|
|
signal.Notify(c, os.Interrupt)
|
|
|
|
signal.Notify(c, syscall.SIGTERM)
|
|
|
|
|
|
|
|
go func() {
|
|
|
|
<-c
|
|
|
|
logrus.Debugln("SIGTERM received.")
|
|
|
|
logrus.Debugln("wait for running builds to finish.")
|
|
|
|
running.Wait()
|
|
|
|
logrus.Debugln("done.")
|
|
|
|
os.Exit(0)
|
|
|
|
}()
|
|
|
|
}
|