package main import ( "context" "flag" "fmt" "net/http" "os" "github.com/peterbourgon/ff/v3" "edge-infra.dev/pkg/edge/monitoring/plank" "edge-infra.dev/pkg/lib/db/postgres" "edge-infra.dev/pkg/lib/logging" "edge-infra.dev/pkg/lib/runtime" "edge-infra.dev/pkg/lib/runtime/healthz" "edge-infra.dev/pkg/lib/runtime/manager" "edge-infra.dev/pkg/lib/runtime/metrics" "edge-infra.dev/pkg/lib/runtime/subscriber" ) var ( fs = flag.NewFlagSet("plank", flag.ContinueOnError) projectID = fs.String("projectID", "", "GCP Project ID for PubSub client") subID = fs.String("subID", "", "The PubSub Subscription ID") host = fs.String("db_host", "localhost", "AlloyDB host") user = fs.String("db_user", "", "AlloyDB user") pass = fs.String("db_password", "", "AlloyDB password") dbName = fs.String("db_name", "", "AlloyDB database name") slackWebhookURL = fs.String("slackWebhookURL", "", "The slack webhook to send the notifications") ) func main() { if err := run(); err != nil { os.Exit(1) } } func run() error { l := logging.NewLogger().WithValues("cmd", "plank").Logger if err := ff.Parse(fs, os.Args[1:], ff.WithEnvVarNoPrefix()); err != nil { l.Error(err, "failed to parse flags") return err } if err := validateConfig(); err != nil { l.Error(err, "failed to validate configuration") return err } // manager opts should really only need to be configured via code edgeOpts := manager.Options{ // todo - should be able to use runtime alias Logger: &l, MetricsBindAddress: metrics.DefaultBindAddress, } edgeMgr, err := runtime.NewManager(edgeOpts) if err != nil { l.Error(err, "failed to create default manager") return err } ctx := context.Background() opts := postgres.DSNOptions{ Host: *host, DBName: *dbName, User: *user, Password: *pass, } client, err := postgres.New(ctx, l, opts) if err != nil { l.Error(err, "failed to create postgres client") return err } defer client.Close() if err := client.Connect(); err != nil { l.Error(err, "failed to connect to postgres database") return err } // todo - add metrics for slack responses and storage p := plank.New(l, *slackWebhookURL, client) subOpts := subscriber.Options{ // todo - should be able to use runtime alias Logger: &l, ProjectID: *projectID, ID: *subID, Handler: p, } sub, err := runtime.NewSubscriber(subOpts) if err != nil { l.Error(err, "failed to create subscriber") return err } if err := edgeMgr.Add(sub); err != nil { l.Error(err, "failed to add subscriber to edge default manager") return err } // if the manager is running not much reason to cause a restart if err := edgeMgr.AddLivezCheck("subscriber", healthz.Ping); err != nil { l.Error(err, "failed to add livez check") return err } // create a default one for now if err := edgeMgr.AddReadyzCheck("subscriber", healthz.Ping); err != nil { // todo - figure out how to check ... maybe something with the context l.Error(err, "failed to add readyz check") return err } // right now this isn't really needed since there is no traffic expected to come from // kube itself, but if we add an API to front plank it will be needed var storageReadyz healthz.Checker = func(_ *http.Request) error { if !client.IsConnected() { return fmt.Errorf("no storage connection") } return nil } if err := edgeMgr.AddReadyzCheck("storage", storageReadyz); err != nil { l.Error(err, "failed to add readyz check") return err } l.Info("starting manager") if err := edgeMgr.Start(runtime.SetupSignalHandler()); err != nil { l.Error(err, "failed to start edge default manager") return err } return nil } func validateConfig() error { // TODO(help_wanted) - upgrade package, WithEnvVarNoPrefix is now deprecated in favor of WithEnvVars if err := ff.Parse(fs, os.Args[1:], ff.WithEnvVarNoPrefix()); err != nil { return err } if projectID == nil || *projectID == "" { return fmt.Errorf("'projectID' arg required") } if subID == nil || *subID == "" { return fmt.Errorf("'subID' arg required") } return nil }