Creates a connection pool credentials lookup function in every database to perform remote authentication.
(poolerSchema, poolerUser string)
| 680 | // Creates a connection pool credentials lookup function in every database to |
| 681 | // perform remote authentication. |
| 682 | func (c *Cluster) installLookupFunction(poolerSchema, poolerUser string) error { |
| 683 | var stmtBytes bytes.Buffer |
| 684 | |
| 685 | c.logger.Info("Installing lookup function") |
| 686 | |
| 687 | // Open a new connection if not yet done. This connection will be used only |
| 688 | // to get the list of databases, not for the actuall installation. |
| 689 | if err := c.initDbConn(); err != nil { |
| 690 | return fmt.Errorf("could not init database connection") |
| 691 | } |
| 692 | defer func() { |
| 693 | if c.connectionIsClosed() { |
| 694 | return |
| 695 | } |
| 696 | |
| 697 | if err := c.closeDbConn(); err != nil { |
| 698 | c.logger.Errorf("could not close database connection: %v", err) |
| 699 | } |
| 700 | }() |
| 701 | |
| 702 | // List of databases we failed to process. At the moment it function just |
| 703 | // like a flag to retry on the next sync, but in the future we may want to |
| 704 | // retry only necessary parts, so let's keep the list. |
| 705 | failedDatabases := []string{} |
| 706 | currentDatabases, err := c.getDatabases() |
| 707 | if err != nil { |
| 708 | msg := "could not get databases to install pooler lookup function: %v" |
| 709 | return fmt.Errorf(msg, err) |
| 710 | } |
| 711 | |
| 712 | // We've got the list of target databases, now close this connection to |
| 713 | // open a new one to every each of them. |
| 714 | if err := c.closeDbConn(); err != nil { |
| 715 | c.logger.Errorf("could not close database connection: %v", err) |
| 716 | } |
| 717 | |
| 718 | templater := template.Must(template.New("sql").Parse(connectionPoolerLookup)) |
| 719 | params := TemplateParams{ |
| 720 | "pooler_schema": poolerSchema, |
| 721 | "pooler_user": poolerUser, |
| 722 | } |
| 723 | |
| 724 | if err := templater.Execute(&stmtBytes, params); err != nil { |
| 725 | msg := "could not prepare sql statement %+v: %v" |
| 726 | return fmt.Errorf(msg, params, err) |
| 727 | } |
| 728 | |
| 729 | for dbname := range currentDatabases { |
| 730 | |
| 731 | if dbname == "template0" || dbname == "template1" { |
| 732 | continue |
| 733 | } |
| 734 | |
| 735 | c.logger.Infof("install pooler lookup function into database '%s'", dbname) |
| 736 | |
| 737 | // golang sql will do retries couple of times if pq driver reports |
| 738 | // connections issues (driver.ErrBadConn), but since our query is |
| 739 | // idempotent, we can retry in a view of other errors (e.g. due to |
nothing calls this directly
no test coverage detected