package main import ( "context" "database/sql" _ "embed" "flag" "fmt" "os" _ "github.com/GoogleCloudPlatform/cloudsql-proxy/proxy/dialers/postgres" "github.com/golang-migrate/migrate/v4/database/postgres" _ "github.com/golang-migrate/migrate/v4/source/file" "github.com/google/uuid" _ "github.com/jackc/pgx/v4/stdlib" // nolint:revive necessary for db driver sqlMetrics "edge-infra.dev/pkg/edge/api/sql/metrics" "edge-infra.dev/pkg/edge/api/sql/migrationmanager" "edge-infra.dev/pkg/edge/api/sql/plugin" "edge-infra.dev/pkg/edge/api/sql/utils" "edge-infra.dev/pkg/lib/gcp/cloudsql" "edge-infra.dev/pkg/lib/logging" "edge-infra.dev/pkg/lib/runtime/manager" "edge-infra.dev/pkg/lib/runtime/metrics" "edge-infra.dev/pkg/sds/emergencyaccess/sql/plugin/emergencyaccess" ) var ( //go:embed config.yaml configFile []byte currentConfig *plugin.Config ) // Sqlconfig represents fields needed to establish a database connection. type Sqlconfig struct { Host string User string DbName string Password string Port string } // newSQLConfig return a new Sqlconfig connection struct. func newSQLConfig() *Sqlconfig { return &Sqlconfig{} } func init() { var err error currentConfig, err = plugin.InitializeWithConfig(configFile) if err != nil { fmt.Printf(utils.Logfmt, utils.SevError, err) panic(err) } } func main() { log := logging.NewLogger().WithName("edge env sql") log.Info("edge env sql migration started") ctx, cancel := context.WithCancel(context.Background()) defer cancel() sqlConfig := newSQLConfig() topLevelProjectID := "" flag.StringVar(&sqlConfig.Host, "dbHost", os.Getenv("SQL_CONNECTION_NAME"), "SQL Connection Host") flag.StringVar(&sqlConfig.User, "dbUser", os.Getenv("SQL_USER"), "SQL Connection Username") flag.StringVar(&sqlConfig.Password, "dbPassword", os.Getenv("SQL_PASSWORD"), "SQL Connection Password") flag.StringVar(&sqlConfig.DbName, "dbName", os.Getenv("SQL_DB_NAME"), "SQL Connection Database Name") flag.StringVar(&sqlConfig.Port, "port", os.Getenv("SQL_PORT"), "Port to connect on") flag.StringVar(&topLevelProjectID, "topLevelProjectID", os.Getenv("TOP_LEVEL_PROJECT_ID"), "project id for foreman cluster") db, err := sqlConfig.createSQLDBConnection() if err != nil { fmt.Printf(utils.Logfmt, utils.SevError, err) panic(err) } driver, err := postgres.WithInstance(db, &postgres.Config{}) if err != nil { fmt.Printf(utils.Logfmt, utils.SevError, err) panic(err) } infraClusters := utils.Clusters{ &utils.Cluster{ EdgeID: uuid.NewString(), Name: "foreman0", ProjectID: topLevelProjectID, //todo get from configmap }, &utils.Cluster{ EdgeID: uuid.NewString(), Name: "banner-infra0", ProjectID: topLevelProjectID, //todo get from configmap }, } currentConfig.Data = append(currentConfig.Data, plugin.Seed{ Name: "seed-infra-clusters.tmpl", Priority: 3, Data: infraClusters, }) perms := utils.Permissions{ { User: fmt.Sprintf("edge-bsl@%s.iam", topLevelProjectID), Role: "ALL", Table: "tenants", }, } currentConfig.Data = append(currentConfig.Data, plugin.Seed{ Name: "seed-role.tmpl", Priority: 4, Data: perms, }) eaData, err := emergencyaccess.GetEASeedData(log, topLevelProjectID) if err != nil { // Log the error but continue as normal, no emergencyaccess data will be // loaded (as long as eaData is empty) log.Error(err, "Error getting EA Seed Data") } currentConfig.Data = append(currentConfig.Data, eaData...) m := sqlMetrics.NewMetrics() m.InitMetrics() mgr, err := manager.New(manager.Options{ MetricsBindAddress: metrics.DefaultBindAddress, }) if err != nil { log.Error(err, "failed to initialize manager") } migrationMgr := migrationmanager.New(currentConfig, driver, log, db, m, cancel) if err != nil { log.Error(err, "failed to create a edgeSQL ops") os.Exit(1) } if err := mgr.Add(migrationMgr); err != nil { log.Error(err, "failed to add edgeSQL ops") os.Exit(1) } if err := mgr.Start(ctx); err != nil { log.Error(err, "failed to start mngr") os.Exit(1) } } // createSQLDBConnection creates a db connection. func (s *Sqlconfig) createSQLDBConnection() (*sql.DB, error) { if s.Host == "localhost" { db, err := sql.Open("pgx", fmt.Sprintf( "host=%s port=%s user=%s password=%s dbname=%s", s.Host, s.Port, s.User, s.Password, s.DbName), ) if err != nil { return nil, err } return db, nil } conn := cloudsql.GCPPostgresConnection(s.Host). DBName(s.DbName). Username(s.User) if s.Password != "" { conn.Password(s.Password) } return conn.NewConnection() }