/* ███████╗██╗░░░██╗███████╗██████╗░███████╗ ██╔════╝╚██╗░██╔╝██╔════╝██╔══██╗██╔════╝ █████╗░░░╚████╔╝░█████╗░░██║░░██║█████╗░░ ██╔══╝░░░░╚██╔╝░░██╔══╝░░██║░░██║██╔══╝░░ ███████╗░░░██║░░░███████╗██████╔╝███████╗ ╚══════╝░░░╚═╝░░░╚══════╝╚═════╝░╚══════╝ CLI program written to populate existing edge info configmap with the correct cluster edge id The cli program can be run like so: Using Storage Bucket: eyede useStorage --databaseHost=ret-edge-dev0-foreman:us-central1:edge-dev0 --databaseName=edge-dev0 --databaseUser=bff-sa@ret-edge-dev0-foreman.iam --topLevelProjectID=ret-edge-dev0-foreman --chariotTopic=chariot-rides Using Database: eyede useDatabase --databaseHost=ret-edge-dev0-foreman:us-central1:edge-dev0 --databaseName=edge-dev0 --databaseUser=bff-sa@ret-edge-dev0-foreman.iam --topLevelProjectID=ret-edge-dev0-foreman --chariotTopic=chariot-rides The following flags are required for the cli to run: databaseHost, databaseName, databaseUser, databasePassword, topLevelProjectID and chariotTopic The dryRun flag is an optional and defaults to false if not specified. launchdarklyKey is also an optional flag that defaults to using cluster id if not set. */ package main import ( "context" "database/sql" "errors" "flag" "fmt" "os" _ "github.com/GoogleCloudPlatform/cloudsql-proxy/proxy/dialers/postgres" "github.com/peterbourgon/ff/v3/ffcli" "edge-infra.dev/pkg/lib/gcp/cloudsql" usedatabase "edge-infra.dev/hack/tools/eyede/use-database" usestorage "edge-infra.dev/hack/tools/eyede/use-storage" eyedeUtils "edge-infra.dev/hack/tools/eyede/utils" "edge-infra.dev/pkg/edge/api/utils" "edge-infra.dev/pkg/lib/cli/commands" ) var ( fs = flag.NewFlagSet("eyede", flag.ExitOnError) databaseHost = fs.String("databaseHost", os.Getenv("DatabaseHost"), "the host of the database to query") databaseName = fs.String("databaseName", os.Getenv("DatabaseName"), "the name of the database to query") databaseUser = fs.String("databaseUser", os.Getenv("DatabaseUser"), "the user of the specified database") topLevelProjectID = fs.String("topLevelProjectID", os.Getenv("TopLevelProjectID"), "the top level project id") chariotTopic = fs.String("chariotTopic", os.Getenv("ChariotTopic"), "chariot pubsub topic") launchdarklyKey = fs.String("launchdarklyKey", os.Getenv("LD_KEY"), "launch darkly sdk key") dryRun = fs.Bool("dryRun", false, "run eyede in dryRun mode and output results in stdout") edgeAPIURL = fs.String("edgeAPIURL", os.Getenv("EDGE_API_URL"), "edge api url") errDatabaseHostRequired = errors.New("error database host is required") errDatabaseNameRequired = errors.New("error database name is required") errDatabaseUserRequired = errors.New("error database user is required") errTopLevelProjectIDRequired = errors.New("error top level project id is required") errChariotTopicRequired = errors.New("error chariot topic is required") errEdgeAPIURLRequired = errors.New("error edge api url is required") ) func main() { err := fs.Parse(os.Args[2:]) if err != nil { fmt.Println("Flag parsing error ", err) os.Exit(1) } if err := validateRequiredFlags(); err != nil { fmt.Println("Flag validation error ", err) os.Exit(1) } if utils.IsNullOrEmpty(launchdarklyKey) { os.Setenv("LD_KEY", *launchdarklyKey) } eyeConfig := eyedeUtils.New() fmt.Println("") fmt.Println(` ███████╗██╗░️░️░██╗███████╗██████╗░███████╗ ██╔════╝╚██╗░██╔╝██╔════╝██╔══██╗██╔════╝ 👁 █████╗░░░╚████╔╝░█████╗░░██║░░██║█████╗░░ ️️👁 ██╔══╝░░░░╚██╔╝░░██╔══╝░░██║░░██║██╔══╝░░ ███████╗░░░██║░░░███████╗██████╔╝███████╗ ╚══════╝░░░╚═╝░░░╚══════╝╚═════╝░╚══════╝ `) fmt.Println("") fmt.Printf("Connecting to Database: %s with user %s\n", *databaseName, *databaseUser) db, err := connectToDatabase() if err != nil { fmt.Println("db connection error occurred ", err) os.Exit(1) } eyeConfig.SetDBConnection(db) useDatabase := eyeConfig.Exec("useDatabase", "eyede useDatabase", "populate the edge-info configmap using the SQL Database", *topLevelProjectID, *chariotTopic, *edgeAPIURL, *dryRun, usedatabase.CreateEdgeInfoConfigMap, fs) useStorage := eyeConfig.Exec("useStorage", "eyede useStorage", "populate the edge-info configmap using the storage buckets", *topLevelProjectID, *chariotTopic, *edgeAPIURL, *dryRun, usestorage.UpdateEdgeInfoConfigMapsInStorage, fs) cmd := &ffcli.Command{ Name: "eyede", ShortUsage: "eyede --databaseHost=ret-edge-dev0-foreman:us-central1:edge-dev0 --databaseName=edge-dev0 --databaseUser=bff-sa@ret-edge-dev0-foreman.iam --topLevelProjectID=ret-edge-dev0-foreman --chariotTopic=chariot-rides --edgeAPIURL=https://dev0.edge-preprod.dev/api/v2", ShortHelp: "populate edge ids for all clusters", Subcommands: []*ffcli.Command{ useDatabase, useStorage, commands.Version(), }, } if err := cmd.ParseAndRun(context.Background(), os.Args[1:]); err != nil { fmt.Fprintf(os.Stderr, "error: %v\n", err) os.Exit(1) } } func validateRequiredFlags() error { if utils.IsNullOrEmpty(databaseHost) { return errDatabaseHostRequired } if utils.IsNullOrEmpty(databaseName) { return errDatabaseNameRequired } if utils.IsNullOrEmpty(databaseUser) { return errDatabaseUserRequired } if utils.IsNullOrEmpty(topLevelProjectID) { return errTopLevelProjectIDRequired } if utils.IsNullOrEmpty(chariotTopic) { return errChariotTopicRequired } if utils.IsNullOrEmpty(edgeAPIURL) { return errEdgeAPIURLRequired } return nil } func connectToDatabase() (*sql.DB, error) { return cloudsql.GCPPostgresConnection(*databaseHost).Username(*databaseUser).DBName(*databaseName).NewConnection() }