Example #1
0
// Broker is a middleware function that initializes the broker
// and adds the broker client to the request context.
func Broker(cli *cli.Context) gin.HandlerFunc {
	secret := cli.String("agent-secret")
	if secret == "" {
		logrus.Fatalf("fatal error. please provide the DRONE_SECRET")
	}

	// setup broker logging.
	log := redlog.New(os.Stderr)
	log.SetLevel(0)
	logger.SetLogger(log)
	if cli.Bool("broker-debug") {
		log.SetLevel(1)
	}

	broker := server.NewServer(
		server.WithCredentials("x-token", secret),
	)
	client := broker.Client()

	var once sync.Once
	return func(c *gin.Context) {
		c.Set(serverKey, broker)
		c.Set(clientKey, client)
		once.Do(func() {
			// this is some really hacky stuff
			// turns out I need to do some refactoring
			// don't judge!
			// will fix in 0.6 release
			ctx := c.Copy()
			client.Connect(
				stomp.WithCredentials("x-token", secret),
			)
			client.Subscribe("/queue/updates", stomp.HandlerFunc(func(m *stomp.Message) {
				go handlers.HandleUpdate(ctx, m.Copy())
			}))
		})
	}
}
Example #2
0
func start(c *cli.Context) {

	log := redlog.New(os.Stderr)
	log.SetLevel(0)
	logger.SetLogger(log)

	// debug level if requested by user
	if c.Bool("debug") {
		logrus.SetLevel(logrus.DebugLevel)

		log.SetLevel(1)
	} else {
		logrus.SetLevel(logrus.WarnLevel)
	}

	var accessToken string
	if c.String("drone-secret") != "" {
		// secretToken := c.String("drone-secret")
		accessToken = c.String("drone-secret")
		// accessToken, _ = token.New(token.AgentToken, "").Sign(secretToken)
	} else {
		accessToken = c.String("drone-token")
	}

	logger.Noticef("connecting to server %s", c.String("drone-server"))

	server := strings.TrimRight(c.String("drone-server"), "/")

	tls, err := dockerclient.TLSConfigFromCertPath(c.String("docker-cert-path"))
	if err == nil {
		tls.InsecureSkipVerify = c.Bool("docker-tls-verify")
	}
	docker, err := dockerclient.NewDockerClient(c.String("docker-host"), tls)
	if err != nil {
		logrus.Fatal(err)
	}

	var client *stomp.Client

	handler := func(m *stomp.Message) {
		running.Add(1)
		defer func() {
			running.Done()
			client.Ack(m.Ack)
		}()

		r := pipeline{
			drone:  client,
			docker: docker,
			config: config{
				platform:   c.String("docker-os") + "/" + c.String("docker-arch"),
				timeout:    c.Duration("timeout"),
				namespace:  c.String("namespace"),
				privileged: c.StringSlice("privileged"),
				pull:       c.BoolT("pull"),
				logs:       int64(c.Int("max-log-size")) * 1000000,
			},
		}

		work := new(model.Work)
		m.Unmarshal(work)
		r.run(work)
	}

	handleSignals()

	backoff := c.Duration("backoff")

	for {
		// dial the drone server to establish a TCP connection.
		client, err = stomp.Dial(server)
		if err != nil {
			logger.Warningf("connection failed, retry in %v. %s", backoff, err)
			<-time.After(backoff)
			continue
		}
		opts := []stomp.MessageOption{
			stomp.WithCredentials("x-token", accessToken),
		}

		// initialize the stomp session and authenticate.
		if err = client.Connect(opts...); err != nil {
			logger.Warningf("session failed, retry in %v. %s", backoff, err)
			<-time.After(backoff)
			continue
		}

		opts = []stomp.MessageOption{
			stomp.WithAck("client"),
			stomp.WithPrefetch(
				c.Int("docker-max-procs"),
			),
		}
		if filter := c.String("filter"); filter != "" {
			opts = append(opts, stomp.WithSelector(filter))
		}

		// subscribe to the pending build queue.
		client.Subscribe("/queue/pending", stomp.HandlerFunc(func(m *stomp.Message) {
			go handler(m) // HACK until we a channel based Subscribe implementation
		}), opts...)

		logger.Noticef("connection established, ready to process builds.")
		<-client.Done()

		logger.Warningf("connection interrupted, attempting to reconnect.")
	}
}