Prevent empty syncs (#922)
There is a possibility to pass nil as one of the specs and an empty spec into syncConnectionPooler. In this case it will perfom a syncronization because nil != empty struct. Avoid such cases and make it testable by returning list of syncronization reasons on top together with the final error.
This commit is contained in:
		
							parent
							
								
									7e8f6687eb
								
							
						
					
					
						commit
						6a689cdc1c
					
				|  | @ -741,7 +741,8 @@ func (c *Cluster) Update(oldSpec, newSpec *acidv1.Postgresql) error { | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	// sync connection pooler
 | 	// sync connection pooler
 | ||||||
| 	if err := c.syncConnectionPooler(oldSpec, newSpec, c.installLookupFunction); err != nil { | 	if _, err := c.syncConnectionPooler(oldSpec, newSpec, | ||||||
|  | 		c.installLookupFunction); err != nil { | ||||||
| 		return fmt.Errorf("could not sync connection pooler: %v", err) | 		return fmt.Errorf("could not sync connection pooler: %v", err) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -111,7 +111,7 @@ func (c *Cluster) Sync(newSpec *acidv1.Postgresql) error { | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	// sync connection pooler
 | 	// sync connection pooler
 | ||||||
| 	if err = c.syncConnectionPooler(&oldSpec, newSpec, c.installLookupFunction); err != nil { | 	if _, err = c.syncConnectionPooler(&oldSpec, newSpec, c.installLookupFunction); err != nil { | ||||||
| 		return fmt.Errorf("could not sync connection pooler: %v", err) | 		return fmt.Errorf("could not sync connection pooler: %v", err) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -620,7 +620,13 @@ func (c *Cluster) syncLogicalBackupJob() error { | ||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (c *Cluster) syncConnectionPooler(oldSpec, newSpec *acidv1.Postgresql, lookup InstallFunction) error { | func (c *Cluster) syncConnectionPooler(oldSpec, | ||||||
|  | 	newSpec *acidv1.Postgresql, | ||||||
|  | 	lookup InstallFunction) (SyncReason, error) { | ||||||
|  | 
 | ||||||
|  | 	var reason SyncReason | ||||||
|  | 	var err error | ||||||
|  | 
 | ||||||
| 	if c.ConnectionPooler == nil { | 	if c.ConnectionPooler == nil { | ||||||
| 		c.ConnectionPooler = &ConnectionPoolerObjects{} | 		c.ConnectionPooler = &ConnectionPoolerObjects{} | ||||||
| 	} | 	} | ||||||
|  | @ -657,20 +663,20 @@ func (c *Cluster) syncConnectionPooler(oldSpec, newSpec *acidv1.Postgresql, look | ||||||
| 				specUser, | 				specUser, | ||||||
| 				c.OpConfig.ConnectionPooler.User) | 				c.OpConfig.ConnectionPooler.User) | ||||||
| 
 | 
 | ||||||
| 			if err := lookup(schema, user); err != nil { | 			if err = lookup(schema, user); err != nil { | ||||||
| 				return err | 				return NoSync, err | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		if err := c.syncConnectionPoolerWorker(oldSpec, newSpec); err != nil { | 		if reason, err = c.syncConnectionPoolerWorker(oldSpec, newSpec); err != nil { | ||||||
| 			c.logger.Errorf("could not sync connection pooler: %v", err) | 			c.logger.Errorf("could not sync connection pooler: %v", err) | ||||||
| 			return err | 			return reason, err | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if oldNeedConnectionPooler && !newNeedConnectionPooler { | 	if oldNeedConnectionPooler && !newNeedConnectionPooler { | ||||||
| 		// delete and cleanup resources
 | 		// delete and cleanup resources
 | ||||||
| 		if err := c.deleteConnectionPooler(); err != nil { | 		if err = c.deleteConnectionPooler(); err != nil { | ||||||
| 			c.logger.Warningf("could not remove connection pooler: %v", err) | 			c.logger.Warningf("could not remove connection pooler: %v", err) | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  | @ -681,20 +687,22 @@ func (c *Cluster) syncConnectionPooler(oldSpec, newSpec *acidv1.Postgresql, look | ||||||
| 			(c.ConnectionPooler.Deployment != nil || | 			(c.ConnectionPooler.Deployment != nil || | ||||||
| 				c.ConnectionPooler.Service != nil) { | 				c.ConnectionPooler.Service != nil) { | ||||||
| 
 | 
 | ||||||
| 			if err := c.deleteConnectionPooler(); err != nil { | 			if err = c.deleteConnectionPooler(); err != nil { | ||||||
| 				c.logger.Warningf("could not remove connection pooler: %v", err) | 				c.logger.Warningf("could not remove connection pooler: %v", err) | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	return nil | 	return reason, nil | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // Synchronize connection pooler resources. Effectively we're interested only in
 | // Synchronize connection pooler resources. Effectively we're interested only in
 | ||||||
| // synchronizing the corresponding deployment, but in case of deployment or
 | // synchronizing the corresponding deployment, but in case of deployment or
 | ||||||
| // service is missing, create it. After checking, also remember an object for
 | // service is missing, create it. After checking, also remember an object for
 | ||||||
| // the future references.
 | // the future references.
 | ||||||
| func (c *Cluster) syncConnectionPoolerWorker(oldSpec, newSpec *acidv1.Postgresql) error { | func (c *Cluster) syncConnectionPoolerWorker(oldSpec, newSpec *acidv1.Postgresql) ( | ||||||
|  | 	SyncReason, error) { | ||||||
|  | 
 | ||||||
| 	deployment, err := c.KubeClient. | 	deployment, err := c.KubeClient. | ||||||
| 		Deployments(c.Namespace). | 		Deployments(c.Namespace). | ||||||
| 		Get(context.TODO(), c.connectionPoolerName(), metav1.GetOptions{}) | 		Get(context.TODO(), c.connectionPoolerName(), metav1.GetOptions{}) | ||||||
|  | @ -706,7 +714,7 @@ func (c *Cluster) syncConnectionPoolerWorker(oldSpec, newSpec *acidv1.Postgresql | ||||||
| 		deploymentSpec, err := c.generateConnectionPoolerDeployment(&newSpec.Spec) | 		deploymentSpec, err := c.generateConnectionPoolerDeployment(&newSpec.Spec) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			msg = "could not generate deployment for connection pooler: %v" | 			msg = "could not generate deployment for connection pooler: %v" | ||||||
| 			return fmt.Errorf(msg, err) | 			return NoSync, fmt.Errorf(msg, err) | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		deployment, err := c.KubeClient. | 		deployment, err := c.KubeClient. | ||||||
|  | @ -714,18 +722,35 @@ func (c *Cluster) syncConnectionPoolerWorker(oldSpec, newSpec *acidv1.Postgresql | ||||||
| 			Create(context.TODO(), deploymentSpec, metav1.CreateOptions{}) | 			Create(context.TODO(), deploymentSpec, metav1.CreateOptions{}) | ||||||
| 
 | 
 | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			return err | 			return NoSync, err | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		c.ConnectionPooler.Deployment = deployment | 		c.ConnectionPooler.Deployment = deployment | ||||||
| 	} else if err != nil { | 	} else if err != nil { | ||||||
| 		return fmt.Errorf("could not get connection pooler deployment to sync: %v", err) | 		msg := "could not get connection pooler deployment to sync: %v" | ||||||
|  | 		return NoSync, fmt.Errorf(msg, err) | ||||||
| 	} else { | 	} else { | ||||||
| 		c.ConnectionPooler.Deployment = deployment | 		c.ConnectionPooler.Deployment = deployment | ||||||
| 
 | 
 | ||||||
| 		// actual synchronization
 | 		// actual synchronization
 | ||||||
| 		oldConnectionPooler := oldSpec.Spec.ConnectionPooler | 		oldConnectionPooler := oldSpec.Spec.ConnectionPooler | ||||||
| 		newConnectionPooler := newSpec.Spec.ConnectionPooler | 		newConnectionPooler := newSpec.Spec.ConnectionPooler | ||||||
|  | 
 | ||||||
|  | 		// sync implementation below assumes that both old and new specs are
 | ||||||
|  | 		// not nil, but it can happen. To avoid any confusion like updating a
 | ||||||
|  | 		// deployment because the specification changed from nil to an empty
 | ||||||
|  | 		// struct (that was initialized somewhere before) replace any nil with
 | ||||||
|  | 		// an empty spec.
 | ||||||
|  | 		if oldConnectionPooler == nil { | ||||||
|  | 			oldConnectionPooler = &acidv1.ConnectionPooler{} | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if newConnectionPooler == nil { | ||||||
|  | 			newConnectionPooler = &acidv1.ConnectionPooler{} | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		c.logger.Infof("Old: %+v, New %+v", oldConnectionPooler, newConnectionPooler) | ||||||
|  | 
 | ||||||
| 		specSync, specReason := c.needSyncConnectionPoolerSpecs(oldConnectionPooler, newConnectionPooler) | 		specSync, specReason := c.needSyncConnectionPoolerSpecs(oldConnectionPooler, newConnectionPooler) | ||||||
| 		defaultsSync, defaultsReason := c.needSyncConnectionPoolerDefaults(newConnectionPooler, deployment) | 		defaultsSync, defaultsReason := c.needSyncConnectionPoolerDefaults(newConnectionPooler, deployment) | ||||||
| 		reason := append(specReason, defaultsReason...) | 		reason := append(specReason, defaultsReason...) | ||||||
|  | @ -736,7 +761,7 @@ func (c *Cluster) syncConnectionPoolerWorker(oldSpec, newSpec *acidv1.Postgresql | ||||||
| 			newDeploymentSpec, err := c.generateConnectionPoolerDeployment(&newSpec.Spec) | 			newDeploymentSpec, err := c.generateConnectionPoolerDeployment(&newSpec.Spec) | ||||||
| 			if err != nil { | 			if err != nil { | ||||||
| 				msg := "could not generate deployment for connection pooler: %v" | 				msg := "could not generate deployment for connection pooler: %v" | ||||||
| 				return fmt.Errorf(msg, err) | 				return reason, fmt.Errorf(msg, err) | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			oldDeploymentSpec := c.ConnectionPooler.Deployment | 			oldDeploymentSpec := c.ConnectionPooler.Deployment | ||||||
|  | @ -746,11 +771,11 @@ func (c *Cluster) syncConnectionPoolerWorker(oldSpec, newSpec *acidv1.Postgresql | ||||||
| 				newDeploymentSpec) | 				newDeploymentSpec) | ||||||
| 
 | 
 | ||||||
| 			if err != nil { | 			if err != nil { | ||||||
| 				return err | 				return reason, err | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			c.ConnectionPooler.Deployment = deployment | 			c.ConnectionPooler.Deployment = deployment | ||||||
| 			return nil | 			return reason, nil | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -768,16 +793,17 @@ func (c *Cluster) syncConnectionPoolerWorker(oldSpec, newSpec *acidv1.Postgresql | ||||||
| 			Create(context.TODO(), serviceSpec, metav1.CreateOptions{}) | 			Create(context.TODO(), serviceSpec, metav1.CreateOptions{}) | ||||||
| 
 | 
 | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			return err | 			return NoSync, err | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		c.ConnectionPooler.Service = service | 		c.ConnectionPooler.Service = service | ||||||
| 	} else if err != nil { | 	} else if err != nil { | ||||||
| 		return fmt.Errorf("could not get connection pooler service to sync: %v", err) | 		msg := "could not get connection pooler service to sync: %v" | ||||||
|  | 		return NoSync, fmt.Errorf(msg, err) | ||||||
| 	} else { | 	} else { | ||||||
| 		// Service updates are not supported and probably not that useful anyway
 | 		// Service updates are not supported and probably not that useful anyway
 | ||||||
| 		c.ConnectionPooler.Service = service | 		c.ConnectionPooler.Service = service | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	return nil | 	return NoSync, nil | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -2,6 +2,7 @@ package cluster | ||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
| 	"fmt" | 	"fmt" | ||||||
|  | 	"strings" | ||||||
| 	"testing" | 	"testing" | ||||||
| 
 | 
 | ||||||
| 	acidv1 "github.com/zalando/postgres-operator/pkg/apis/acid.zalan.do/v1" | 	acidv1 "github.com/zalando/postgres-operator/pkg/apis/acid.zalan.do/v1" | ||||||
|  | @ -17,7 +18,7 @@ func int32ToPointer(value int32) *int32 { | ||||||
| 	return &value | 	return &value | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func deploymentUpdated(cluster *Cluster, err error) error { | func deploymentUpdated(cluster *Cluster, err error, reason SyncReason) error { | ||||||
| 	if cluster.ConnectionPooler.Deployment.Spec.Replicas == nil || | 	if cluster.ConnectionPooler.Deployment.Spec.Replicas == nil || | ||||||
| 		*cluster.ConnectionPooler.Deployment.Spec.Replicas != 2 { | 		*cluster.ConnectionPooler.Deployment.Spec.Replicas != 2 { | ||||||
| 		return fmt.Errorf("Wrong nubmer of instances") | 		return fmt.Errorf("Wrong nubmer of instances") | ||||||
|  | @ -26,7 +27,7 @@ func deploymentUpdated(cluster *Cluster, err error) error { | ||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func objectsAreSaved(cluster *Cluster, err error) error { | func objectsAreSaved(cluster *Cluster, err error, reason SyncReason) error { | ||||||
| 	if cluster.ConnectionPooler == nil { | 	if cluster.ConnectionPooler == nil { | ||||||
| 		return fmt.Errorf("Connection pooler resources are empty") | 		return fmt.Errorf("Connection pooler resources are empty") | ||||||
| 	} | 	} | ||||||
|  | @ -42,7 +43,7 @@ func objectsAreSaved(cluster *Cluster, err error) error { | ||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func objectsAreDeleted(cluster *Cluster, err error) error { | func objectsAreDeleted(cluster *Cluster, err error, reason SyncReason) error { | ||||||
| 	if cluster.ConnectionPooler != nil { | 	if cluster.ConnectionPooler != nil { | ||||||
| 		return fmt.Errorf("Connection pooler was not deleted") | 		return fmt.Errorf("Connection pooler was not deleted") | ||||||
| 	} | 	} | ||||||
|  | @ -50,6 +51,16 @@ func objectsAreDeleted(cluster *Cluster, err error) error { | ||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | func noEmptySync(cluster *Cluster, err error, reason SyncReason) error { | ||||||
|  | 	for _, msg := range reason { | ||||||
|  | 		if strings.HasPrefix(msg, "update [] from '<nil>' to '") { | ||||||
|  | 			return fmt.Errorf("There is an empty reason, %s", msg) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
| func TestConnectionPoolerSynchronization(t *testing.T) { | func TestConnectionPoolerSynchronization(t *testing.T) { | ||||||
| 	testName := "Test connection pooler synchronization" | 	testName := "Test connection pooler synchronization" | ||||||
| 	var cluster = New( | 	var cluster = New( | ||||||
|  | @ -91,15 +102,15 @@ func TestConnectionPoolerSynchronization(t *testing.T) { | ||||||
| 
 | 
 | ||||||
| 	clusterNewDefaultsMock := *cluster | 	clusterNewDefaultsMock := *cluster | ||||||
| 	clusterNewDefaultsMock.KubeClient = k8sutil.NewMockKubernetesClient() | 	clusterNewDefaultsMock.KubeClient = k8sutil.NewMockKubernetesClient() | ||||||
| 	cluster.OpConfig.ConnectionPooler.Image = "pooler:2.0" |  | ||||||
| 	cluster.OpConfig.ConnectionPooler.NumberOfInstances = int32ToPointer(2) |  | ||||||
| 
 | 
 | ||||||
| 	tests := []struct { | 	tests := []struct { | ||||||
| 		subTest string | 		subTest          string | ||||||
| 		oldSpec *acidv1.Postgresql | 		oldSpec          *acidv1.Postgresql | ||||||
| 		newSpec *acidv1.Postgresql | 		newSpec          *acidv1.Postgresql | ||||||
| 		cluster *Cluster | 		cluster          *Cluster | ||||||
| 		check   func(cluster *Cluster, err error) error | 		defaultImage     string | ||||||
|  | 		defaultInstances int32 | ||||||
|  | 		check            func(cluster *Cluster, err error, reason SyncReason) error | ||||||
| 	}{ | 	}{ | ||||||
| 		{ | 		{ | ||||||
| 			subTest: "create if doesn't exist", | 			subTest: "create if doesn't exist", | ||||||
|  | @ -113,8 +124,10 @@ func TestConnectionPoolerSynchronization(t *testing.T) { | ||||||
| 					ConnectionPooler: &acidv1.ConnectionPooler{}, | 					ConnectionPooler: &acidv1.ConnectionPooler{}, | ||||||
| 				}, | 				}, | ||||||
| 			}, | 			}, | ||||||
| 			cluster: &clusterMissingObjects, | 			cluster:          &clusterMissingObjects, | ||||||
| 			check:   objectsAreSaved, | 			defaultImage:     "pooler:1.0", | ||||||
|  | 			defaultInstances: 1, | ||||||
|  | 			check:            objectsAreSaved, | ||||||
| 		}, | 		}, | ||||||
| 		{ | 		{ | ||||||
| 			subTest: "create if doesn't exist with a flag", | 			subTest: "create if doesn't exist with a flag", | ||||||
|  | @ -126,8 +139,10 @@ func TestConnectionPoolerSynchronization(t *testing.T) { | ||||||
| 					EnableConnectionPooler: boolToPointer(true), | 					EnableConnectionPooler: boolToPointer(true), | ||||||
| 				}, | 				}, | ||||||
| 			}, | 			}, | ||||||
| 			cluster: &clusterMissingObjects, | 			cluster:          &clusterMissingObjects, | ||||||
| 			check:   objectsAreSaved, | 			defaultImage:     "pooler:1.0", | ||||||
|  | 			defaultInstances: 1, | ||||||
|  | 			check:            objectsAreSaved, | ||||||
| 		}, | 		}, | ||||||
| 		{ | 		{ | ||||||
| 			subTest: "create from scratch", | 			subTest: "create from scratch", | ||||||
|  | @ -139,8 +154,10 @@ func TestConnectionPoolerSynchronization(t *testing.T) { | ||||||
| 					ConnectionPooler: &acidv1.ConnectionPooler{}, | 					ConnectionPooler: &acidv1.ConnectionPooler{}, | ||||||
| 				}, | 				}, | ||||||
| 			}, | 			}, | ||||||
| 			cluster: &clusterMissingObjects, | 			cluster:          &clusterMissingObjects, | ||||||
| 			check:   objectsAreSaved, | 			defaultImage:     "pooler:1.0", | ||||||
|  | 			defaultInstances: 1, | ||||||
|  | 			check:            objectsAreSaved, | ||||||
| 		}, | 		}, | ||||||
| 		{ | 		{ | ||||||
| 			subTest: "delete if not needed", | 			subTest: "delete if not needed", | ||||||
|  | @ -152,8 +169,10 @@ func TestConnectionPoolerSynchronization(t *testing.T) { | ||||||
| 			newSpec: &acidv1.Postgresql{ | 			newSpec: &acidv1.Postgresql{ | ||||||
| 				Spec: acidv1.PostgresSpec{}, | 				Spec: acidv1.PostgresSpec{}, | ||||||
| 			}, | 			}, | ||||||
| 			cluster: &clusterMock, | 			cluster:          &clusterMock, | ||||||
| 			check:   objectsAreDeleted, | 			defaultImage:     "pooler:1.0", | ||||||
|  | 			defaultInstances: 1, | ||||||
|  | 			check:            objectsAreDeleted, | ||||||
| 		}, | 		}, | ||||||
| 		{ | 		{ | ||||||
| 			subTest: "cleanup if still there", | 			subTest: "cleanup if still there", | ||||||
|  | @ -163,8 +182,10 @@ func TestConnectionPoolerSynchronization(t *testing.T) { | ||||||
| 			newSpec: &acidv1.Postgresql{ | 			newSpec: &acidv1.Postgresql{ | ||||||
| 				Spec: acidv1.PostgresSpec{}, | 				Spec: acidv1.PostgresSpec{}, | ||||||
| 			}, | 			}, | ||||||
| 			cluster: &clusterDirtyMock, | 			cluster:          &clusterDirtyMock, | ||||||
| 			check:   objectsAreDeleted, | 			defaultImage:     "pooler:1.0", | ||||||
|  | 			defaultInstances: 1, | ||||||
|  | 			check:            objectsAreDeleted, | ||||||
| 		}, | 		}, | ||||||
| 		{ | 		{ | ||||||
| 			subTest: "update deployment", | 			subTest: "update deployment", | ||||||
|  | @ -182,8 +203,10 @@ func TestConnectionPoolerSynchronization(t *testing.T) { | ||||||
| 					}, | 					}, | ||||||
| 				}, | 				}, | ||||||
| 			}, | 			}, | ||||||
| 			cluster: &clusterMock, | 			cluster:          &clusterMock, | ||||||
| 			check:   deploymentUpdated, | 			defaultImage:     "pooler:1.0", | ||||||
|  | 			defaultInstances: 1, | ||||||
|  | 			check:            deploymentUpdated, | ||||||
| 		}, | 		}, | ||||||
| 		{ | 		{ | ||||||
| 			subTest: "update image from changed defaults", | 			subTest: "update image from changed defaults", | ||||||
|  | @ -197,14 +220,40 @@ func TestConnectionPoolerSynchronization(t *testing.T) { | ||||||
| 					ConnectionPooler: &acidv1.ConnectionPooler{}, | 					ConnectionPooler: &acidv1.ConnectionPooler{}, | ||||||
| 				}, | 				}, | ||||||
| 			}, | 			}, | ||||||
| 			cluster: &clusterNewDefaultsMock, | 			cluster:          &clusterNewDefaultsMock, | ||||||
| 			check:   deploymentUpdated, | 			defaultImage:     "pooler:2.0", | ||||||
|  | 			defaultInstances: 2, | ||||||
|  | 			check:            deploymentUpdated, | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			subTest: "there is no sync from nil to an empty spec", | ||||||
|  | 			oldSpec: &acidv1.Postgresql{ | ||||||
|  | 				Spec: acidv1.PostgresSpec{ | ||||||
|  | 					EnableConnectionPooler: boolToPointer(true), | ||||||
|  | 					ConnectionPooler:       nil, | ||||||
|  | 				}, | ||||||
|  | 			}, | ||||||
|  | 			newSpec: &acidv1.Postgresql{ | ||||||
|  | 				Spec: acidv1.PostgresSpec{ | ||||||
|  | 					EnableConnectionPooler: boolToPointer(true), | ||||||
|  | 					ConnectionPooler:       &acidv1.ConnectionPooler{}, | ||||||
|  | 				}, | ||||||
|  | 			}, | ||||||
|  | 			cluster:          &clusterMock, | ||||||
|  | 			defaultImage:     "pooler:1.0", | ||||||
|  | 			defaultInstances: 1, | ||||||
|  | 			check:            noEmptySync, | ||||||
| 		}, | 		}, | ||||||
| 	} | 	} | ||||||
| 	for _, tt := range tests { | 	for _, tt := range tests { | ||||||
| 		err := tt.cluster.syncConnectionPooler(tt.oldSpec, tt.newSpec, mockInstallLookupFunction) | 		tt.cluster.OpConfig.ConnectionPooler.Image = tt.defaultImage | ||||||
|  | 		tt.cluster.OpConfig.ConnectionPooler.NumberOfInstances = | ||||||
|  | 			int32ToPointer(tt.defaultInstances) | ||||||
| 
 | 
 | ||||||
| 		if err := tt.check(tt.cluster, err); err != nil { | 		reason, err := tt.cluster.syncConnectionPooler(tt.oldSpec, | ||||||
|  | 			tt.newSpec, mockInstallLookupFunction) | ||||||
|  | 
 | ||||||
|  | 		if err := tt.check(tt.cluster, err, reason); err != nil { | ||||||
| 			t.Errorf("%s [%s]: Could not synchronize, %+v", | 			t.Errorf("%s [%s]: Could not synchronize, %+v", | ||||||
| 				testName, tt.subTest, err) | 				testName, tt.subTest, err) | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | @ -73,3 +73,8 @@ type ClusterStatus struct { | ||||||
| type TemplateParams map[string]interface{} | type TemplateParams map[string]interface{} | ||||||
| 
 | 
 | ||||||
| type InstallFunction func(schema string, user string) error | type InstallFunction func(schema string, user string) error | ||||||
|  | 
 | ||||||
|  | type SyncReason []string | ||||||
|  | 
 | ||||||
|  | // no sync happened, empty value
 | ||||||
|  | var NoSync SyncReason = []string{} | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue