forked from dolthub/vitess
-
Notifications
You must be signed in to change notification settings - Fork 0
/
dbconfigs.go
214 lines (194 loc) · 7.24 KB
/
dbconfigs.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
/*
Copyright 2017 Google Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Package dbconfigs is reusable by vt tools to load
// the db configs file.
package dbconfigs
import (
"encoding/json"
"flag"
"fmt"
"vitess.io/vitess/go/mysql"
"vitess.io/vitess/go/vt/log"
)
// We keep a global singleton for the db configs, and that's the one
// the flags will change
var dbConfigs = DBConfigs{
SidecarDBName: "_vt",
}
// DBConfigFlag describes which flags we need
type DBConfigFlag int
// config flags
const (
EmptyConfig DBConfigFlag = 0
AppConfig DBConfigFlag = 1 << iota
AppDebugConfig
// AllPrivs user should have more privileges than App (should include possibility to do
// schema changes and write to internal Vitess tables), but it shouldn't have SUPER
// privilege like Dba has.
AllPrivsConfig
DbaConfig
FilteredConfig
ReplConfig
)
// redactedPassword is used in redacted configs so it's not in logs.
const redactedPassword = "****"
// The flags will change the global singleton
func registerConnFlags(connParams *mysql.ConnParams, name string) {
flag.StringVar(&connParams.Host, "db-config-"+name+"-host", "", "db "+name+" connection host")
flag.IntVar(&connParams.Port, "db-config-"+name+"-port", 0, "db "+name+" connection port")
flag.StringVar(&connParams.Uname, "db-config-"+name+"-uname", "", "db "+name+" connection uname")
flag.StringVar(&connParams.Pass, "db-config-"+name+"-pass", "", "db "+name+" connection pass")
flag.StringVar(&connParams.DbName, "db-config-"+name+"-dbname", "", "db "+name+" connection dbname")
flag.StringVar(&connParams.UnixSocket, "db-config-"+name+"-unixsocket", "", "db "+name+" connection unix socket")
flag.StringVar(&connParams.Charset, "db-config-"+name+"-charset", "", "db "+name+" connection charset")
flag.Uint64Var(&connParams.Flags, "db-config-"+name+"-flags", 0, "db "+name+" connection flags")
flag.StringVar(&connParams.SslCa, "db-config-"+name+"-ssl-ca", "", "db "+name+" connection ssl ca")
flag.StringVar(&connParams.SslCaPath, "db-config-"+name+"-ssl-ca-path", "", "db "+name+" connection ssl ca path")
flag.StringVar(&connParams.SslCert, "db-config-"+name+"-ssl-cert", "", "db "+name+" connection ssl certificate")
flag.StringVar(&connParams.SslKey, "db-config-"+name+"-ssl-key", "", "db "+name+" connection ssl key")
}
// RegisterFlags registers the flags for the given DBConfigFlag.
// For instance, vttablet will register client, dba and repl.
// Returns all registered flags.
func RegisterFlags(flags DBConfigFlag) DBConfigFlag {
if flags == EmptyConfig {
panic("No DB config is provided.")
}
registeredFlags := EmptyConfig
if AppConfig&flags != 0 {
registerConnFlags(&dbConfigs.App, "app")
registeredFlags |= AppConfig
}
if AppDebugConfig&flags != 0 {
registerConnFlags(&dbConfigs.AppDebug, "appdebug")
registeredFlags |= AppDebugConfig
}
if AllPrivsConfig&flags != 0 {
registerConnFlags(&dbConfigs.AllPrivs, "allprivs")
registeredFlags |= AllPrivsConfig
}
if DbaConfig&flags != 0 {
registerConnFlags(&dbConfigs.Dba, "dba")
registeredFlags |= DbaConfig
}
if FilteredConfig&flags != 0 {
registerConnFlags(&dbConfigs.Filtered, "filtered")
registeredFlags |= FilteredConfig
}
if ReplConfig&flags != 0 {
registerConnFlags(&dbConfigs.Repl, "repl")
registeredFlags |= ReplConfig
}
return registeredFlags
}
// initConnParams may overwrite the socket file,
// and refresh the password to check that works.
func initConnParams(cp *mysql.ConnParams, socketFile string) error {
// Always try to connect with the socket if provided.
if socketFile != "" {
cp.UnixSocket = socketFile
}
// See if the CredentialsServer is working. We do not use the
// result for anything, this is just a check.
_, err := WithCredentials(cp)
return err
}
// DBConfigs is all we need for a smart tablet server:
// - App access with db name for serving app queries
// - AllPrivs access for administrative actions (like schema changes)
// that should be done without SUPER privilege
// - Dba access for any dba-type operation (db creation, replication, ...)
// - Filtered access for filtered replication
// - Replication access to change master
// - SidecarDBName for storing operational metadata
type DBConfigs struct {
App mysql.ConnParams
AppDebug mysql.ConnParams
AllPrivs mysql.ConnParams
Dba mysql.ConnParams
Filtered mysql.ConnParams
Repl mysql.ConnParams
SidecarDBName string
}
func (dbcfgs *DBConfigs) String() string {
if dbcfgs.App.Pass != redactedPassword {
panic("Cannot log a non-redacted DBConfig")
}
if dbcfgs.AppDebug.Pass != redactedPassword {
panic("Cannot log a non-redacted DBConfig")
}
data, err := json.MarshalIndent(dbcfgs, "", " ")
if err != nil {
return err.Error()
}
return string(data)
}
// Redact will remove the password, so the object can be logged
func (dbcfgs *DBConfigs) Redact() {
dbcfgs.App.Pass = redactedPassword
dbcfgs.AppDebug.Pass = redactedPassword
dbcfgs.AllPrivs.Pass = redactedPassword
dbcfgs.Dba.Pass = redactedPassword
dbcfgs.Filtered.Pass = redactedPassword
dbcfgs.Repl.Pass = redactedPassword
}
// IsZero returns true if DBConfigs was uninitialized.
func (dbcfgs *DBConfigs) IsZero() bool {
return dbcfgs.App.Uname == ""
}
// Init will initialize app, allprivs, dba, filtered and repl configs.
func Init(socketFile string, flags DBConfigFlag) (*DBConfigs, error) {
if flags == EmptyConfig {
panic("No DB config is provided.")
}
if AppConfig&flags != 0 {
if err := initConnParams(&dbConfigs.App, socketFile); err != nil {
return nil, fmt.Errorf("app dbconfig cannot be initialized: %v", err)
}
}
if AppDebugConfig&flags != 0 {
if err := initConnParams(&dbConfigs.AppDebug, socketFile); err != nil {
return nil, fmt.Errorf("appdebug dbconfig cannot be initialized: %v", err)
}
}
if AllPrivsConfig&flags != 0 {
if err := initConnParams(&dbConfigs.AllPrivs, socketFile); err != nil {
return nil, fmt.Errorf("allprivs dbconfig cannot be initialized: %v", err)
}
}
if DbaConfig&flags != 0 {
if err := initConnParams(&dbConfigs.Dba, socketFile); err != nil {
return nil, fmt.Errorf("dba dbconfig cannot be initialized: %v", err)
}
}
if FilteredConfig&flags != 0 {
if err := initConnParams(&dbConfigs.Filtered, socketFile); err != nil {
return nil, fmt.Errorf("filtered dbconfig cannot be initialized: %v", err)
}
}
if ReplConfig&flags != 0 {
if err := initConnParams(&dbConfigs.Repl, socketFile); err != nil {
return nil, fmt.Errorf("repl dbconfig cannot be initialized: %v", err)
}
}
// the Dba connection is not linked to a specific database
// (allows us to create them)
if dbConfigs.Dba.DbName != "" {
log.Warningf("dba dbname is set to '%v', ignoring the value", dbConfigs.Dba.DbName)
dbConfigs.Dba.DbName = ""
}
toLog := dbConfigs
toLog.Redact()
log.Infof("DBConfigs: %v\n", toLog.String())
return &dbConfigs, nil
}