keel/main.go

253 lines
6.2 KiB
Go
Raw Normal View History

2017-06-10 11:23:51 +00:00
package main
import (
"os"
"os/signal"
"time"
2017-06-27 21:28:46 +00:00
"context"
netContext "golang.org/x/net/context"
2017-06-10 23:25:36 +00:00
2017-06-27 20:08:43 +00:00
"github.com/rusenask/keel/bot"
2017-07-07 22:58:48 +00:00
"github.com/rusenask/keel/constants"
"github.com/rusenask/keel/extension/notification"
2017-06-10 11:23:51 +00:00
"github.com/rusenask/keel/provider"
"github.com/rusenask/keel/provider/helm"
2017-06-10 11:23:51 +00:00
"github.com/rusenask/keel/provider/kubernetes"
2017-07-02 19:09:54 +00:00
"github.com/rusenask/keel/registry"
2017-07-28 22:20:24 +00:00
"github.com/rusenask/keel/secrets"
2017-06-12 20:54:11 +00:00
"github.com/rusenask/keel/trigger/http"
2017-07-02 19:09:54 +00:00
"github.com/rusenask/keel/trigger/poll"
2017-06-10 23:25:36 +00:00
"github.com/rusenask/keel/trigger/pubsub"
2017-06-10 11:23:51 +00:00
"github.com/rusenask/keel/types"
2017-06-15 07:47:40 +00:00
"github.com/rusenask/keel/version"
2017-06-10 11:23:51 +00:00
2017-07-07 22:58:48 +00:00
// extensions
_ "github.com/rusenask/keel/extension/notification/slack"
_ "github.com/rusenask/keel/extension/notification/webhook"
2017-06-10 11:23:51 +00:00
log "github.com/Sirupsen/logrus"
)
2017-06-10 23:25:36 +00:00
// gcloud pubsub related config
const (
2017-06-11 21:52:18 +00:00
EnvTriggerPubSub = "PUBSUB" // set to 1 or something to enable pub/sub trigger
2017-07-02 19:09:54 +00:00
EnvTriggerPoll = "POLL" // set to 1 or something to enable poll trigger
2017-06-11 21:52:18 +00:00
EnvProjectID = "PROJECT_ID"
EnvHelmProvider = "HELM_PROVIDER" // helm provider
EnvHelmTillerAddress = "TILLER_ADDRESS" // helm provider
2017-06-10 23:25:36 +00:00
)
// kubernetes config, if empty - will default to InCluster
const (
EnvKubernetesConfig = "KUBERNETES_CONFIG"
)
2017-06-11 21:52:18 +00:00
// EnvDebug - set to 1 or anything else to enable debug logging
const EnvDebug = "DEBUG"
2017-06-10 11:23:51 +00:00
func main() {
2017-06-15 07:47:40 +00:00
ver := version.GetKeelVersion()
log.WithFields(log.Fields{
"os": ver.OS,
"build_date": ver.BuildDate,
"revision": ver.Revision,
"version": ver.Version,
"go_version": ver.GoVersion,
"arch": ver.Arch,
2017-07-23 17:15:16 +00:00
}).Info("keel starting..")
2017-06-15 07:47:40 +00:00
2017-06-11 21:52:18 +00:00
if os.Getenv(EnvDebug) != "" {
log.SetLevel(log.DebugLevel)
}
2017-07-07 22:58:48 +00:00
// setting up triggers
ctx, cancel := netContext.WithCancel(context.Background())
defer cancel()
notifCfg := &notification.Config{
Attempts: 10,
}
sender := notification.New(ctx)
_, err := sender.Configure(notifCfg)
if err != nil {
log.WithFields(log.Fields{
"error": err,
}).Fatal("main: failed to configure notification sender manager")
}
2017-06-10 11:23:51 +00:00
// getting k8s provider
2017-06-10 23:25:36 +00:00
k8sCfg := &kubernetes.Opts{}
if os.Getenv(EnvKubernetesConfig) != "" {
k8sCfg.ConfigPath = os.Getenv(EnvKubernetesConfig)
} else {
k8sCfg.InCluster = true
}
2017-06-11 21:52:18 +00:00
implementer, err := kubernetes.NewKubernetesImplementer(k8sCfg)
if err != nil {
log.WithFields(log.Fields{
"error": err,
"config": k8sCfg,
}).Fatal("main: failed to create kubernetes implementer")
}
2017-06-12 20:49:01 +00:00
// setting up providers
providers := setupProviders(implementer, sender)
2017-06-12 20:49:01 +00:00
2017-07-28 22:20:24 +00:00
secretsGetter := secrets.NewGetter(implementer)
teardownTriggers := setupTriggers(ctx, providers, secretsGetter)
2017-06-12 20:49:01 +00:00
2017-06-27 21:28:46 +00:00
teardownBot, err := setupBot(implementer)
if err != nil {
log.WithFields(log.Fields{
"error": err,
}).Fatal("main: failed to setup slack bot")
}
2017-06-12 20:49:01 +00:00
signalChan := make(chan os.Signal, 1)
cleanupDone := make(chan bool)
signal.Notify(signalChan, os.Interrupt)
go func() {
for _ = range signalChan {
log.Info("received an interrupt, closing connection...")
go func() {
select {
case <-time.After(10 * time.Second):
log.Info("connection shutdown took too long, exiting... ")
close(cleanupDone)
return
case <-cleanupDone:
return
}
}()
// teardownProviders()
providers.Stop()
2017-06-12 20:49:01 +00:00
teardownTriggers()
2017-06-27 21:28:46 +00:00
teardownBot()
2017-06-12 20:49:01 +00:00
cleanupDone <- true
}
}()
<-cleanupDone
}
// setupProviders - setting up available providers. New providers should be initialised here and added to
// provider map
func setupProviders(k8sImplementer kubernetes.Implementer, sender notification.Sender) (providers provider.Providers) {
var enabledProviders []provider.Provider
2017-07-07 22:58:48 +00:00
k8sProvider, err := kubernetes.NewProvider(k8sImplementer, sender)
2017-06-10 11:23:51 +00:00
if err != nil {
log.WithFields(log.Fields{
"error": err,
2017-06-12 20:49:01 +00:00
}).Fatal("main.setupProviders: failed to create kubernetes provider")
2017-06-10 11:23:51 +00:00
}
go k8sProvider.Start()
enabledProviders = append(enabledProviders, k8sProvider)
2017-06-10 11:23:51 +00:00
if os.Getenv(EnvHelmProvider) == "1" {
tillerAddr := os.Getenv(EnvHelmTillerAddress)
helmImplementer := helm.NewHelmImplementer(tillerAddr)
helmProvider := helm.NewProvider(helmImplementer, sender)
2017-06-10 11:23:51 +00:00
go helmProvider.Start()
enabledProviders = append(enabledProviders, helmProvider)
2017-06-12 20:49:01 +00:00
}
providers = provider.New(enabledProviders)
return providers
2017-06-12 20:49:01 +00:00
}
2017-06-27 21:28:46 +00:00
func setupBot(k8sImplementer kubernetes.Implementer) (teardown func(), err error) {
2017-07-07 22:58:48 +00:00
if os.Getenv(constants.EnvSlackToken) != "" {
2017-06-27 21:28:46 +00:00
botName := "keel"
2017-07-07 22:58:48 +00:00
if os.Getenv(constants.EnvSlackBotName) != "" {
botName = os.Getenv(constants.EnvSlackBotName)
2017-06-27 21:28:46 +00:00
}
2017-07-07 22:58:48 +00:00
token := os.Getenv(constants.EnvSlackToken)
2017-07-08 17:22:43 +00:00
slackBot := bot.New(botName, token, k8sImplementer)
2017-06-27 21:28:46 +00:00
ctx, cancel := context.WithCancel(context.Background())
err := slackBot.Start(ctx)
if err != nil {
cancel()
return nil, err
}
teardown := func() {
// cancelling context
cancel()
}
return teardown, nil
}
2017-06-27 20:08:43 +00:00
2017-06-27 21:28:46 +00:00
return func() {}, nil
2017-06-27 20:08:43 +00:00
}
2017-06-12 20:49:01 +00:00
// setupTriggers - setting up triggers. New triggers should be added to this function. Each trigger
// should go through all providers (or not if there is a reason) and submit events)
2017-07-28 22:20:24 +00:00
func setupTriggers(ctx context.Context, providers provider.Providers, secretsGetter secrets.Getter) (teardown func()) {
2017-06-12 20:49:01 +00:00
2017-06-12 20:54:11 +00:00
// setting up generic http webhook server
whs := http.NewTriggerServer(&http.Opts{
2017-06-10 11:23:51 +00:00
Port: types.KeelDefaultPort,
Providers: providers,
})
go whs.Start()
2017-06-12 20:49:01 +00:00
// checking whether pubsub (GCR) trigger is enabled
2017-06-10 23:25:36 +00:00
if os.Getenv(EnvTriggerPubSub) != "" {
projectID := os.Getenv(EnvProjectID)
if projectID == "" {
2017-06-12 20:49:01 +00:00
log.Fatalf("main.setupTriggers: project ID env variable not set")
2017-06-10 23:25:36 +00:00
return
}
2017-06-14 19:03:37 +00:00
ps, err := pubsub.NewPubsubSubscriber(&pubsub.Opts{
2017-06-11 21:52:18 +00:00
ProjectID: projectID,
Providers: providers,
2017-06-10 23:25:36 +00:00
})
if err != nil {
log.WithFields(log.Fields{
"error": err,
2017-06-12 20:49:01 +00:00
}).Fatal("main.setupTriggers: failed to create gcloud pubsub subscriber")
2017-06-10 23:25:36 +00:00
return
}
2017-06-11 21:52:18 +00:00
subManager := pubsub.NewDefaultManager(projectID, providers, ps)
2017-06-11 21:52:18 +00:00
go subManager.Start(ctx)
2017-06-10 23:25:36 +00:00
}
2017-07-23 17:15:16 +00:00
if os.Getenv(EnvTriggerPoll) != "0" {
2017-07-02 19:09:54 +00:00
registryClient := registry.New()
watcher := poll.NewRepositoryWatcher(providers, registryClient)
2017-07-28 22:20:24 +00:00
pollManager := poll.NewPollManager(providers, watcher, secretsGetter)
2017-07-02 19:09:54 +00:00
// start poll manager, will finish with ctx
2017-07-02 20:21:39 +00:00
go watcher.Start(ctx)
2017-07-02 19:09:54 +00:00
go pollManager.Start(ctx)
}
2017-06-12 20:49:01 +00:00
teardown = func() {
whs.Stop()
}
2017-06-10 11:23:51 +00:00
2017-06-12 20:49:01 +00:00
return teardown
2017-06-10 11:23:51 +00:00
}