diff --git a/lib/gat/modes/zalando_operator_discovery/server.go b/lib/gat/modes/zalando_operator_discovery/server.go index 0d24169d6520341505b3c24e2a63c6d10b7bb8ba..7be5bf357862db56e54f4a22b632001cd2c348fb 100644 --- a/lib/gat/modes/zalando_operator_discovery/server.go +++ b/lib/gat/modes/zalando_operator_discovery/server.go @@ -32,6 +32,11 @@ type mapKey struct { Database string } +type toAddDetails struct { + SecretUser string + Name string +} + type Server struct { config *Config @@ -103,7 +108,7 @@ func (T *Server) addPostgresql(psql *v1acid.Postgresql) { T.updatePostgresql(nil, psql) } -func (T *Server) addPool(name string, creds auth.Credentials, user, database string) { +func (T *Server) addPool(name string, userCreds, serverCreds auth.Credentials, database string) { d := dialer.Net{ Network: "tcp", Address: name + "." + T.config.Namespace + ".svc.cluster.local:5432", // TODO(garet) lookup port from config map @@ -112,13 +117,13 @@ func (T *Server) addPool(name string, creds auth.Credentials, user, database str SSLConfig: &tls.Config{ InsecureSkipVerify: true, }, - Credentials: creds, + Credentials: serverCreds, Database: database, }, } poolOptions := pool.Options{ - Credentials: creds, + Credentials: userCreds, } p := transaction.NewPool(poolOptions) @@ -129,25 +134,29 @@ func (T *Server) addPool(name string, creds auth.Credentials, user, database str p.AddRecipe("service", r) - T.pools.Add(user, database, p) + T.pools.Add(userCreds.GetUsername(), database, p) } func (T *Server) updatePostgresql(oldPsql *v1acid.Postgresql, newPsql *v1acid.Postgresql) { + toRemove := make(map[mapKey]struct{}) + toAdd := make(map[mapKey]toAddDetails) + if oldPsql != nil { log.Print("removed databases: ", oldPsql.Spec.Databases) log.Print("removed users: ", oldPsql.Spec.Users) for user := range oldPsql.Spec.Users { for database := range oldPsql.Spec.Databases { - p := T.pools.Remove(user, database) - if p != nil { - p.Close() - } + toRemove[mapKey{ + User: user, + Database: database, + }] = struct{}{} + if oldPsql.Spec.NumberOfInstances > 1 { // there are replicas, delete them - p = T.pools.Remove(user+"_ro", database) - if p != nil { - p.Close() - } + toRemove[mapKey{ + User: user + "_ro", + Database: database, + }] = struct{}{} } } } @@ -156,8 +165,53 @@ func (T *Server) updatePostgresql(oldPsql *v1acid.Postgresql, newPsql *v1acid.Po log.Print("added databases: ", newPsql.Spec.Databases) log.Print("added users: ", newPsql.Spec.Users) for user := range newPsql.Spec.Users { + for database := range newPsql.Spec.Databases { + key := mapKey{ + User: user, + Database: database, + } + if _, ok := toRemove[key]; ok { + delete(toRemove, key) + } else { + toAdd[key] = toAddDetails{ + SecretUser: user, + Name: newPsql.Name, + } + } + + if newPsql.Spec.NumberOfInstances > 1 { + key = mapKey{ + User: user + "_ro", + Database: database, + } + if _, ok := toRemove[key]; ok { + delete(toRemove, key) + } else { + toAdd[key] = toAddDetails{ + SecretUser: user, + Name: newPsql.Name + "-repl", + } + } + } + } + } + } + + for pair := range toRemove { + p := T.pools.Remove(pair.User, pair.Database) + if p != nil { + p.Close() + } + log.Print("removed pool username=", pair.User, " database=", pair.Database) + } + + credentialsCache := make(map[string]credentials.Cleartext) + + for pair, details := range toAdd { + creds, ok := credentialsCache[details.SecretUser] + if !ok { // TODO(garet) lookup config map to get this format (what a pain) - secretName := user + "." + newPsql.Name + ".credentials." + v1acid.PostgresCRDResourceKind + "." + acidzalando.GroupName + secretName := details.SecretUser + "." + newPsql.Name + ".credentials." + v1acid.PostgresCRDResourceKind + "." + acidzalando.GroupName secret, err := T.k8s.Secrets(T.config.Namespace).Get(context.Background(), secretName, v1.GetOptions{}) if err != nil { @@ -171,19 +225,17 @@ func (T *Server) updatePostgresql(oldPsql *v1acid.Postgresql, newPsql *v1acid.Po return } - creds := credentials.Cleartext{ - Username: user, + creds = credentials.Cleartext{ + Username: details.SecretUser, Password: string(password), } - - for database := range newPsql.Spec.Databases { - T.addPool(newPsql.Name, creds, user, database) - - if newPsql.Spec.NumberOfInstances > 1 { - T.addPool(newPsql.Name+"-repl", creds, user+"_ro", database) - } - } } + userCreds := credentials.Cleartext{ + Username: pair.User, + Password: creds.Password, + } + T.addPool(details.Name, userCreds, creds, pair.Database) + log.Print("added pool username=", pair.User, " database=", pair.Database) } }