...
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
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
29
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
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
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