...

Source file src/edge-infra.dev/pkg/edge/controllers/sequel/config.go

Documentation: edge-infra.dev/pkg/edge/controllers/sequel

     1  package sequel
     2  
     3  import (
     4  	"database/sql"
     5  	"flag"
     6  	"fmt"
     7  
     8  	"github.com/peterbourgon/ff/v3"
     9  
    10  	"edge-infra.dev/pkg/edge/controllers/sequel/dbctl"
    11  	"edge-infra.dev/pkg/lib/gcp/cloudsql"
    12  )
    13  
    14  // config is the controllers application config
    15  type config struct {
    16  	host           string
    17  	connectionName string
    18  	name           string
    19  	user           string
    20  	password       string
    21  	port           string
    22  	db             *dbctl.DB
    23  	namespace      string
    24  	projectID      string
    25  	concurrency    int
    26  }
    27  
    28  // newConfig creates the controller config, reading initial values via flags and
    29  // environment variables via ff
    30  func newConfig(args []string) (*config, error) {
    31  	fs := flag.NewFlagSet("sequel", flag.ExitOnError)
    32  
    33  	cfg := &config{}
    34  	cfg.bindFlags(fs)
    35  
    36  	if err := ff.Parse(fs, args, ff.WithEnvVarNoPrefix()); err != nil {
    37  		return nil, fmt.Errorf("failed to parse configuration: %w", err)
    38  	}
    39  	if err := cfg.validate(); err != nil {
    40  		return nil, fmt.Errorf("invalid configuration: %w", err)
    41  	}
    42  
    43  	return cfg, nil
    44  }
    45  
    46  // afterParse computes additional values after flags have been parsed
    47  func (c *config) afterParse() error {
    48  	if c.db == nil {
    49  		conn, err := c.connectDatabase()
    50  		if err != nil {
    51  			return err
    52  		}
    53  		c.db = dbctl.New(conn)
    54  	}
    55  
    56  	return nil
    57  }
    58  
    59  func (c *config) validate() error {
    60  	if c.name == "" {
    61  		return fmt.Errorf("--name is required")
    62  	}
    63  
    64  	if c.user == "" {
    65  		return fmt.Errorf("--user is required")
    66  	}
    67  
    68  	if c.projectID == "" {
    69  		return fmt.Errorf("--project-id is required")
    70  	}
    71  
    72  	return nil
    73  }
    74  
    75  func (c *config) connectDatabase() (*sql.DB, error) {
    76  	edgeDB := &cloudsql.EdgePostgres{}
    77  	switch {
    78  	case c.connectionName != "":
    79  		edgeDB = cloudsql.GCPPostgresConnection(c.connectionName)
    80  	case c.connectionName == "":
    81  		edgeDB = cloudsql.PostgresConnection(c.host, c.port).Password(c.password)
    82  	}
    83  	dbConnection, err := edgeDB.
    84  		DBName(c.name).
    85  		Username(c.user).
    86  		NewConnection()
    87  	if err != nil {
    88  		return nil, err
    89  	}
    90  	if err := dbConnection.Ping(); err != nil {
    91  		return nil, err
    92  	}
    93  	return dbConnection, nil
    94  }
    95  
    96  // bindFlags binds the controller's configuration to command line flags.
    97  func (c *config) bindFlags(fs *flag.FlagSet) {
    98  	fs.StringVar(&c.connectionName, "connection-name", "",
    99  		"CloudSQL postgres database connection name")
   100  	fs.StringVar(&c.host, "host", "",
   101  		"CloudSQL postgres database host")
   102  	fs.StringVar(&c.port, "port", "",
   103  		"CloudSQL postgres database port")
   104  	fs.StringVar(&c.name, "name", "",
   105  		"CloudSQL postgres database name")
   106  	fs.StringVar(&c.user, "user", "",
   107  		"CloudSQL postgres database user")
   108  	fs.StringVar(&c.password, "password", "",
   109  		"CloudSQL postgres database password")
   110  	fs.StringVar(&c.namespace, "namespace", "",
   111  		"K8s namespace the controller is deployed to")
   112  	fs.StringVar(&c.projectID, "project-id", "",
   113  		"GCP project id to store database password secret")
   114  	fs.IntVar(&c.concurrency, "concurrency", 8,
   115  		"amount of database users to reconcile at a time")
   116  }
   117  

View as plain text