Sync due to defaults
Since we can miss it while checking only spec
This commit is contained in:
parent
3e98832703
commit
037d7120ef
|
|
@ -1206,7 +1206,7 @@ func (c *Cluster) deletePatroniClusterConfigMaps() error {
|
||||||
// Test if two connection pool configuration needs to be synced. For simplicity
|
// Test if two connection pool configuration needs to be synced. For simplicity
|
||||||
// compare not the actual K8S objects, but the configuration itself and request
|
// compare not the actual K8S objects, but the configuration itself and request
|
||||||
// sync if there is any difference.
|
// sync if there is any difference.
|
||||||
func (c *Cluster) needSyncConnPoolDeployments(oldSpec, newSpec *acidv1.ConnectionPool) (sync bool, reasons []string) {
|
func (c *Cluster) needSyncConnPoolSpecs(oldSpec, newSpec *acidv1.ConnectionPool) (sync bool, reasons []string) {
|
||||||
reasons = []string{}
|
reasons = []string{}
|
||||||
sync = false
|
sync = false
|
||||||
|
|
||||||
|
|
@ -1228,3 +1228,69 @@ func (c *Cluster) needSyncConnPoolDeployments(oldSpec, newSpec *acidv1.Connectio
|
||||||
|
|
||||||
return sync, reasons
|
return sync, reasons
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func syncResources(a, b *v1.ResourceRequirements) bool {
|
||||||
|
for _, res := range []v1.ResourceName{
|
||||||
|
v1.ResourceCPU,
|
||||||
|
v1.ResourceMemory,
|
||||||
|
} {
|
||||||
|
if !a.Limits[res].Equal(b.Limits[res]) ||
|
||||||
|
!a.Requests[res].Equal(b.Requests[res]) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if we need to synchronize connection pool deploymend due to new
|
||||||
|
// defaults, that are different from what we see in the DeploymentSpec
|
||||||
|
func (c *Cluster) needSyncConnPoolDefaults(
|
||||||
|
spec *acidv1.ConnectionPool,
|
||||||
|
deployment *appsv1.Deployment) (sync bool, reasons []string) {
|
||||||
|
|
||||||
|
reasons = []string{}
|
||||||
|
sync = false
|
||||||
|
|
||||||
|
config := c.OpConfig.ConnectionPool
|
||||||
|
podTemplate := deployment.Spec.Template
|
||||||
|
poolContainer := podTemplate.Spec.Containers[constants.ConnPoolContainer]
|
||||||
|
|
||||||
|
if spec.NumberOfInstances == nil &&
|
||||||
|
deployment.Spec.Replicas != config.NumberOfInstances {
|
||||||
|
|
||||||
|
sync = true
|
||||||
|
msg := fmt.Sprintf("NumberOfInstances is different (%d vs %d)",
|
||||||
|
deployment.Spec.Replicas, config.NumberOfInstances)
|
||||||
|
reasons = append(reasons, msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
if spec.DockerImage == "" &&
|
||||||
|
poolContainer.Image != config.Image {
|
||||||
|
|
||||||
|
sync = true
|
||||||
|
msg := fmt.Sprintf("DockerImage is different (%s vs %s)",
|
||||||
|
poolContainer.Image, config.Image)
|
||||||
|
reasons = append(reasons, msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
expectedResources, err := generateResourceRequirements(spec.Resources,
|
||||||
|
c.makeDefaultConnPoolResources())
|
||||||
|
|
||||||
|
// 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) {
|
||||||
|
sync = true
|
||||||
|
msg := fmt.Sprintf("Resources are different (%+v vs %+v)",
|
||||||
|
poolContainer.Resources, expectedResources)
|
||||||
|
reasons = append(reasons, msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
c.logger.Warningf("Cannot generate expected resources, %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return sync, reasons
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1754,7 +1754,7 @@ func (c *Cluster) generateConnPoolPodTemplate(spec *acidv1.PostgresSpec) (
|
||||||
secretSelector := func(key string) *v1.SecretKeySelector {
|
secretSelector := func(key string) *v1.SecretKeySelector {
|
||||||
return &v1.SecretKeySelector{
|
return &v1.SecretKeySelector{
|
||||||
LocalObjectReference: v1.LocalObjectReference{
|
LocalObjectReference: v1.LocalObjectReference{
|
||||||
Name: c.credentialSecretName(c.OpConfig.SuperUsername),
|
Name: c.credentialSecretName(c.OpConfig.ConnectionPool.User),
|
||||||
},
|
},
|
||||||
Key: key,
|
Key: key,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -702,8 +702,10 @@ func (c *Cluster) syncConnectionPoolWorker(oldSpec, newSpec *acidv1.Postgresql)
|
||||||
// actual synchronization
|
// actual synchronization
|
||||||
oldConnPool := oldSpec.Spec.ConnectionPool
|
oldConnPool := oldSpec.Spec.ConnectionPool
|
||||||
newConnPool := newSpec.Spec.ConnectionPool
|
newConnPool := newSpec.Spec.ConnectionPool
|
||||||
sync, reason := c.needSyncConnPoolDeployments(oldConnPool, newConnPool)
|
specSync, specReason := c.needSyncConnPoolSpecs(oldConnPool, newConnPool)
|
||||||
if sync {
|
defaultsSync, defaultsReason := c.needSyncConnPoolDefaults(newConnPool, deployment)
|
||||||
|
reason := append(specReason, defaultsReason...)
|
||||||
|
if specSync || defaultsSync {
|
||||||
c.logger.Infof("Update connection pool deployment %s, reason: %s",
|
c.logger.Infof("Update connection pool deployment %s, reason: %s",
|
||||||
c.connPoolName(), reason)
|
c.connPoolName(), reason)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -88,6 +88,11 @@ func TestConnPoolSynchronization(t *testing.T) {
|
||||||
Service: &v1.Service{},
|
Service: &v1.Service{},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
clusterNewDefaultsMock := *cluster
|
||||||
|
clusterNewDefaultsMock.KubeClient = k8sutil.NewMockKubernetesClient()
|
||||||
|
cluster.OpConfig.ConnectionPool.Image = "pooler:2.0"
|
||||||
|
cluster.OpConfig.ConnectionPool.NumberOfInstances = int32ToPointer(2)
|
||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
subTest string
|
subTest string
|
||||||
oldSpec *acidv1.Postgresql
|
oldSpec *acidv1.Postgresql
|
||||||
|
|
@ -166,6 +171,21 @@ func TestConnPoolSynchronization(t *testing.T) {
|
||||||
cluster: &clusterMock,
|
cluster: &clusterMock,
|
||||||
check: deploymentUpdated,
|
check: deploymentUpdated,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
subTest: "update image from changed defaults",
|
||||||
|
oldSpec: &acidv1.Postgresql{
|
||||||
|
Spec: acidv1.PostgresSpec{
|
||||||
|
ConnectionPool: &acidv1.ConnectionPool{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
newSpec: &acidv1.Postgresql{
|
||||||
|
Spec: acidv1.PostgresSpec{
|
||||||
|
ConnectionPool: &acidv1.ConnectionPool{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
cluster: &clusterNewDefaultsMock,
|
||||||
|
check: deploymentUpdated,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
err := tt.cluster.syncConnectionPool(tt.oldSpec, tt.newSpec)
|
err := tt.cluster.syncConnectionPool(tt.oldSpec, tt.newSpec)
|
||||||
|
|
|
||||||
|
|
@ -10,4 +10,6 @@ const (
|
||||||
ConnectionPoolDefaultCpuLimit = "100m"
|
ConnectionPoolDefaultCpuLimit = "100m"
|
||||||
ConnectionPoolDefaultMemoryRequest = "100Mi"
|
ConnectionPoolDefaultMemoryRequest = "100Mi"
|
||||||
ConnectionPoolDefaultMemoryLimit = "100Mi"
|
ConnectionPoolDefaultMemoryLimit = "100Mi"
|
||||||
|
|
||||||
|
ConnPoolContainer = 0
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -300,6 +300,18 @@ func (mock *mockDeployment) Get(name string, opts metav1.GetOptions) (*apiappsv1
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: "test-deployment",
|
Name: "test-deployment",
|
||||||
},
|
},
|
||||||
|
Spec: apiappsv1.DeploymentSpec{
|
||||||
|
Replicas: int32ToPointer(1),
|
||||||
|
Template: v1.PodTemplateSpec{
|
||||||
|
Spec: v1.PodSpec{
|
||||||
|
Containers: []v1.Container{
|
||||||
|
v1.Container{
|
||||||
|
Image: "pooler:1.0",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue