Call me pooler, not pool (#883)

* rename pooler parts and add example to manifest
* update codegen
* fix manifest and add more details to docs
* reflect renaming also in e2e tests
This commit is contained in:
Felix Kunde
2020-04-01 10:34:03 +02:00
committed by GitHub
parent e6eb10d28a
commit b43b22dfcc
35 changed files with 651 additions and 633 deletions
+53 -53
View File
@@ -50,14 +50,14 @@ type Config struct {
PodServiceAccountRoleBinding *rbacv1.RoleBinding
}
// K8S objects that are belongs to a connection pool
type ConnectionPoolObjects struct {
// K8S objects that are belongs to a connection pooler
type ConnectionPoolerObjects struct {
Deployment *appsv1.Deployment
Service *v1.Service
// It could happen that a connection pool was enabled, but the operator was
// not able to properly process a corresponding event or was restarted. In
// this case we will miss missing/require situation and a lookup function
// It could happen that a connection pooler was enabled, but the operator
// was not able to properly process a corresponding event or was restarted.
// In this case we will miss missing/require situation and a lookup function
// will not be installed. To avoid synchronizing it all the time to prevent
// this, we can remember the result in memory at least until the next
// restart.
@@ -69,7 +69,7 @@ type kubeResources struct {
Endpoints map[PostgresRole]*v1.Endpoints
Secrets map[types.UID]*v1.Secret
Statefulset *appsv1.StatefulSet
ConnectionPool *ConnectionPoolObjects
ConnectionPooler *ConnectionPoolerObjects
PodDisruptionBudget *policybeta1.PodDisruptionBudget
//Pods are treated separately
//PVCs are treated separately
@@ -337,24 +337,24 @@ func (c *Cluster) Create() error {
c.logger.Errorf("could not list resources: %v", err)
}
// Create connection pool deployment and services if necessary. Since we
// need to peform some operations with the database itself (e.g. install
// Create connection pooler deployment and services if necessary. Since we
// need to perform some operations with the database itself (e.g. install
// lookup function), do it as the last step, when everything is available.
//
// Do not consider connection pool as a strict requirement, and if
// Do not consider connection pooler as a strict requirement, and if
// something fails, report warning
if c.needConnectionPool() {
if c.ConnectionPool != nil {
c.logger.Warning("Connection pool already exists in the cluster")
if c.needConnectionPooler() {
if c.ConnectionPooler != nil {
c.logger.Warning("Connection pooler already exists in the cluster")
return nil
}
connPool, err := c.createConnectionPool(c.installLookupFunction)
connectionPooler, err := c.createConnectionPooler(c.installLookupFunction)
if err != nil {
c.logger.Warningf("could not create connection pool: %v", err)
c.logger.Warningf("could not create connection pooler: %v", err)
return nil
}
c.logger.Infof("connection pool %q has been successfully created",
util.NameFromMeta(connPool.Deployment.ObjectMeta))
c.logger.Infof("connection pooler %q has been successfully created",
util.NameFromMeta(connectionPooler.Deployment.ObjectMeta))
}
return nil
@@ -612,11 +612,11 @@ func (c *Cluster) Update(oldSpec, newSpec *acidv1.Postgresql) error {
}
}
// connection pool needs one system user created, which is done in
// connection pooler needs one system user created, which is done in
// initUsers. Check if it needs to be called.
sameUsers := reflect.DeepEqual(oldSpec.Spec.Users, newSpec.Spec.Users)
needConnPool := c.needConnectionPoolWorker(&newSpec.Spec)
if !sameUsers || needConnPool {
needConnectionPooler := c.needConnectionPoolerWorker(&newSpec.Spec)
if !sameUsers || needConnectionPooler {
c.logger.Debugf("syncing secrets")
if err := c.initUsers(); err != nil {
c.logger.Errorf("could not init users: %v", err)
@@ -740,9 +740,9 @@ func (c *Cluster) Update(oldSpec, newSpec *acidv1.Postgresql) error {
}
}
// sync connection pool
if err := c.syncConnectionPool(oldSpec, newSpec, c.installLookupFunction); err != nil {
return fmt.Errorf("could not sync connection pool: %v", err)
// sync connection pooler
if err := c.syncConnectionPooler(oldSpec, newSpec, c.installLookupFunction); err != nil {
return fmt.Errorf("could not sync connection pooler: %v", err)
}
return nil
@@ -796,11 +796,11 @@ func (c *Cluster) Delete() {
c.logger.Warningf("could not remove leftover patroni objects; %v", err)
}
// Delete connection pool objects anyway, even if it's not mentioned in the
// Delete connection pooler objects anyway, even if it's not mentioned in the
// manifest, just to not keep orphaned components in case if something went
// wrong
if err := c.deleteConnectionPool(); err != nil {
c.logger.Warningf("could not remove connection pool: %v", err)
if err := c.deleteConnectionPooler(); err != nil {
c.logger.Warningf("could not remove connection pooler: %v", err)
}
}
@@ -869,32 +869,32 @@ func (c *Cluster) initSystemUsers() {
Password: util.RandomPassword(constants.PasswordLength),
}
// Connection pool user is an exception, if requested it's going to be
// Connection pooler user is an exception, if requested it's going to be
// created by operator as a normal pgUser
if c.needConnectionPool() {
// initialize empty connection pool if not done yet
if c.Spec.ConnectionPool == nil {
c.Spec.ConnectionPool = &acidv1.ConnectionPool{}
if c.needConnectionPooler() {
// initialize empty connection pooler if not done yet
if c.Spec.ConnectionPooler == nil {
c.Spec.ConnectionPooler = &acidv1.ConnectionPooler{}
}
username := util.Coalesce(
c.Spec.ConnectionPool.User,
c.OpConfig.ConnectionPool.User)
c.Spec.ConnectionPooler.User,
c.OpConfig.ConnectionPooler.User)
// connection pooler application should be able to login with this role
connPoolUser := spec.PgUser{
Origin: spec.RoleConnectionPool,
connectionPoolerUser := spec.PgUser{
Origin: spec.RoleConnectionPooler,
Name: username,
Flags: []string{constants.RoleFlagLogin},
Password: util.RandomPassword(constants.PasswordLength),
}
if _, exists := c.pgUsers[username]; !exists {
c.pgUsers[username] = connPoolUser
c.pgUsers[username] = connectionPoolerUser
}
if _, exists := c.systemUsers[constants.ConnectionPoolUserKeyName]; !exists {
c.systemUsers[constants.ConnectionPoolUserKeyName] = connPoolUser
if _, exists := c.systemUsers[constants.ConnectionPoolerUserKeyName]; !exists {
c.systemUsers[constants.ConnectionPoolerUserKeyName] = connectionPoolerUser
}
}
}
@@ -1224,10 +1224,10 @@ func (c *Cluster) deletePatroniClusterConfigMaps() error {
return c.deleteClusterObject(get, deleteConfigMapFn, "configmap")
}
// Test if two connection pool configuration needs to be synced. For simplicity
// Test if two connection pooler configuration needs to be synced. For simplicity
// compare not the actual K8S objects, but the configuration itself and request
// sync if there is any difference.
func (c *Cluster) needSyncConnPoolSpecs(oldSpec, newSpec *acidv1.ConnectionPool) (sync bool, reasons []string) {
func (c *Cluster) needSyncConnectionPoolerSpecs(oldSpec, newSpec *acidv1.ConnectionPooler) (sync bool, reasons []string) {
reasons = []string{}
sync = false
@@ -1264,21 +1264,21 @@ func syncResources(a, b *v1.ResourceRequirements) bool {
return false
}
// Check if we need to synchronize connection pool deployment due to new
// Check if we need to synchronize connection pooler deployment due to new
// defaults, that are different from what we see in the DeploymentSpec
func (c *Cluster) needSyncConnPoolDefaults(
spec *acidv1.ConnectionPool,
func (c *Cluster) needSyncConnectionPoolerDefaults(
spec *acidv1.ConnectionPooler,
deployment *appsv1.Deployment) (sync bool, reasons []string) {
reasons = []string{}
sync = false
config := c.OpConfig.ConnectionPool
config := c.OpConfig.ConnectionPooler
podTemplate := deployment.Spec.Template
poolContainer := podTemplate.Spec.Containers[constants.ConnPoolContainer]
poolerContainer := podTemplate.Spec.Containers[constants.ConnectionPoolerContainer]
if spec == nil {
spec = &acidv1.ConnectionPool{}
spec = &acidv1.ConnectionPooler{}
}
if spec.NumberOfInstances == nil &&
@@ -1291,25 +1291,25 @@ func (c *Cluster) needSyncConnPoolDefaults(
}
if spec.DockerImage == "" &&
poolContainer.Image != config.Image {
poolerContainer.Image != config.Image {
sync = true
msg := fmt.Sprintf("DockerImage is different (having %s, required %s)",
poolContainer.Image, config.Image)
poolerContainer.Image, config.Image)
reasons = append(reasons, msg)
}
expectedResources, err := generateResourceRequirements(spec.Resources,
c.makeDefaultConnPoolResources())
c.makeDefaultConnectionPoolerResources())
// An error to generate expected resources means something is not quite
// right, but for the purpose of robustness do not panic here, just report
// and ignore resources comparison (in the worst case there will be no
// updates for new resource values).
if err == nil && syncResources(&poolContainer.Resources, expectedResources) {
if err == nil && syncResources(&poolerContainer.Resources, expectedResources) {
sync = true
msg := fmt.Sprintf("Resources are different (having %+v, required %+v)",
poolContainer.Resources, expectedResources)
poolerContainer.Resources, expectedResources)
reasons = append(reasons, msg)
}
@@ -1317,13 +1317,13 @@ func (c *Cluster) needSyncConnPoolDefaults(
c.logger.Warningf("Cannot generate expected resources, %v", err)
}
for _, env := range poolContainer.Env {
for _, env := range poolerContainer.Env {
if spec.User == "" && env.Name == "PGUSER" {
ref := env.ValueFrom.SecretKeyRef.LocalObjectReference
if ref.Name != c.credentialSecretName(config.User) {
sync = true
msg := fmt.Sprintf("Pool user is different (having %s, required %s)",
msg := fmt.Sprintf("pooler user is different (having %s, required %s)",
ref.Name, config.User)
reasons = append(reasons, msg)
}
@@ -1331,7 +1331,7 @@ func (c *Cluster) needSyncConnPoolDefaults(
if spec.Schema == "" && env.Name == "PGSCHEMA" && env.Value != config.Schema {
sync = true
msg := fmt.Sprintf("Pool schema is different (having %s, required %s)",
msg := fmt.Sprintf("pooler schema is different (having %s, required %s)",
env.Value, config.Schema)
reasons = append(reasons, msg)
}