patch Pg config on spec.Patroni changes
This commit is contained in:
		
							parent
							
								
									fb1dc2265c
								
							
						
					
					
						commit
						b3f58f2f16
					
				| 
						 | 
					@ -81,7 +81,7 @@ func (ps *PostgresStatus) UnmarshalJSON(data []byte) error {
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		metaErr := json.Unmarshal(data, &status)
 | 
							metaErr := json.Unmarshal(data, &status)
 | 
				
			||||||
		if metaErr != nil {
 | 
							if metaErr != nil {
 | 
				
			||||||
			return fmt.Errorf("Could not parse status: %v; err %v", string(data), metaErr)
 | 
								return fmt.Errorf("could not parse status: %v; err %v", string(data), metaErr)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		tmp.PostgresClusterStatus = status
 | 
							tmp.PostgresClusterStatus = status
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,7 +2,9 @@ package cluster
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"context"
 | 
						"context"
 | 
				
			||||||
 | 
						"encoding/json"
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
 | 
						"reflect"
 | 
				
			||||||
	"regexp"
 | 
						"regexp"
 | 
				
			||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
| 
						 | 
					@ -409,7 +411,7 @@ func (c *Cluster) syncStatefulSet() error {
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if instanceRestartRequired {
 | 
							if instanceRestartRequired {
 | 
				
			||||||
			c.logger.Debugln("restarting Postgres server within pods")
 | 
								c.logger.Debugf("restarting Postgres server within pod %s", podName)
 | 
				
			||||||
			ttl, ok := config["ttl"].(int32)
 | 
								ttl, ok := config["ttl"].(int32)
 | 
				
			||||||
			if !ok {
 | 
								if !ok {
 | 
				
			||||||
				ttl = 30
 | 
									ttl = 30
 | 
				
			||||||
| 
						 | 
					@ -494,29 +496,71 @@ func (c *Cluster) checkAndSetGlobalPostgreSQLConfiguration(pod *v1.Pod, patroniC
 | 
				
			||||||
		restartRequired bool
 | 
							restartRequired bool
 | 
				
			||||||
	)
 | 
						)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// we need to extract those options from the cluster manifest.
 | 
						configToSet := make(map[string]interface{})
 | 
				
			||||||
	optionsToSet := make(map[string]string)
 | 
						parametersToSet := make(map[string]string)
 | 
				
			||||||
	desiredConfig := c.Spec.Parameters
 | 
						effectivePgParameters := make(map[string]interface{})
 | 
				
			||||||
	effectiveConfig := patroniConfig["postgresql"].(map[string]interface{})
 | 
					 | 
				
			||||||
	effectiveParameters := effectiveConfig["parameters"].(map[string]interface{})
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for desiredOption, desiredValue := range desiredConfig {
 | 
						// read effective Patroni config if set
 | 
				
			||||||
		effectiveValue, exists := effectiveParameters[desiredOption]
 | 
						if patroniConfig != nil {
 | 
				
			||||||
		if isBootstrapOnlyParameter(desiredOption) && (effectiveValue != desiredValue || !exists) {
 | 
							effectivePostgresql := patroniConfig["postgresql"].(map[string]interface{})
 | 
				
			||||||
			optionsToSet[desiredOption] = desiredValue
 | 
							effectivePgParameters = effectivePostgresql[patroniPGParametersParameterName].(map[string]interface{})
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// compare parameters under postgresql section with c.Spec.Postgresql.Parameters from manifest
 | 
				
			||||||
 | 
						desiredPgParameters := c.Spec.Parameters
 | 
				
			||||||
 | 
						for desiredOption, desiredValue := range desiredPgParameters {
 | 
				
			||||||
 | 
							effectiveValue := effectivePgParameters[desiredOption]
 | 
				
			||||||
 | 
							if isBootstrapOnlyParameter(desiredOption) && (effectiveValue != desiredValue) {
 | 
				
			||||||
 | 
								parametersToSet[desiredOption] = desiredValue
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if len(optionsToSet) == 0 {
 | 
						if len(parametersToSet) > 0 {
 | 
				
			||||||
 | 
							configToSet["postgresql"] = map[string]interface{}{patroniPGParametersParameterName: parametersToSet}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// compare other options from config with c.Spec.Patroni from manifest
 | 
				
			||||||
 | 
						desiredPatroniConfig := c.Spec.Patroni
 | 
				
			||||||
 | 
						if desiredPatroniConfig.LoopWait > 0 && desiredPatroniConfig.LoopWait != uint32(patroniConfig["loop_wait"].(float64)) {
 | 
				
			||||||
 | 
							configToSet["loop_wait"] = desiredPatroniConfig.LoopWait
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if desiredPatroniConfig.MaximumLagOnFailover > 0 && desiredPatroniConfig.MaximumLagOnFailover != float32(patroniConfig["maximum_lag_on_failover"].(float64)) {
 | 
				
			||||||
 | 
							configToSet["maximum_lag_on_failover"] = desiredPatroniConfig.MaximumLagOnFailover
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if desiredPatroniConfig.PgHba != nil && !reflect.DeepEqual(desiredPatroniConfig.PgHba, (patroniConfig["pg_hba"])) {
 | 
				
			||||||
 | 
							configToSet["pg_hba"] = desiredPatroniConfig.PgHba
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if desiredPatroniConfig.RetryTimeout > 0 && desiredPatroniConfig.RetryTimeout != uint32(patroniConfig["retry_timeout"].(float64)) {
 | 
				
			||||||
 | 
							configToSet["retry_timeout"] = desiredPatroniConfig.RetryTimeout
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if desiredPatroniConfig.Slots != nil && !reflect.DeepEqual(desiredPatroniConfig.Slots, patroniConfig["slots"]) {
 | 
				
			||||||
 | 
							configToSet["slots"] = desiredPatroniConfig.Slots
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if desiredPatroniConfig.SynchronousMode != patroniConfig["synchronous_mode"] {
 | 
				
			||||||
 | 
							configToSet["synchronous_mode"] = desiredPatroniConfig.SynchronousMode
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if desiredPatroniConfig.SynchronousModeStrict != patroniConfig["synchronous_mode_strict"] {
 | 
				
			||||||
 | 
							configToSet["synchronous_mode_strict"] = desiredPatroniConfig.SynchronousModeStrict
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if desiredPatroniConfig.TTL > 0 && desiredPatroniConfig.TTL != uint32(patroniConfig["ttl"].(float64)) {
 | 
				
			||||||
 | 
							configToSet["ttl"] = desiredPatroniConfig.TTL
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if len(configToSet) == 0 {
 | 
				
			||||||
		return restartRequired, nil
 | 
							return restartRequired, nil
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						configToSetJson, err := json.Marshal(configToSet)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							c.logger.Debugf("could not convert config patch to JSON: %v", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// try all pods until the first one that is successful, as it doesn't matter which pod
 | 
						// try all pods until the first one that is successful, as it doesn't matter which pod
 | 
				
			||||||
	// carries the request to change configuration through
 | 
						// carries the request to change configuration through
 | 
				
			||||||
	podName := util.NameFromMeta(pod.ObjectMeta)
 | 
						podName := util.NameFromMeta(pod.ObjectMeta)
 | 
				
			||||||
	c.logger.Debugf("calling Patroni API on a pod %s to set the following Postgres options: %v",
 | 
						c.logger.Debugf("calling Patroni API on a pod %s to set the following Postgres options: %s",
 | 
				
			||||||
		podName, optionsToSet)
 | 
							podName, configToSetJson)
 | 
				
			||||||
	if err = c.patroni.SetPostgresParameters(pod, optionsToSet); err == nil {
 | 
						if err = c.patroni.SetConfig(pod, configToSet); err == nil {
 | 
				
			||||||
		restartRequired = true
 | 
							restartRequired = true
 | 
				
			||||||
		return restartRequired, nil
 | 
							return restartRequired, nil
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -32,6 +32,7 @@ type Interface interface {
 | 
				
			||||||
	GetMemberData(server *v1.Pod) (MemberData, error)
 | 
						GetMemberData(server *v1.Pod) (MemberData, error)
 | 
				
			||||||
	Restart(server *v1.Pod) error
 | 
						Restart(server *v1.Pod) error
 | 
				
			||||||
	GetConfig(server *v1.Pod) (map[string]interface{}, error)
 | 
						GetConfig(server *v1.Pod) (map[string]interface{}, error)
 | 
				
			||||||
 | 
						SetConfig(server *v1.Pod, config map[string]interface{}) error
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Patroni API client
 | 
					// Patroni API client
 | 
				
			||||||
| 
						 | 
					@ -163,6 +164,20 @@ func (p *Patroni) SetPostgresParameters(server *v1.Pod, parameters map[string]st
 | 
				
			||||||
	return p.httpPostOrPatch(http.MethodPatch, apiURLString+configPath, buf)
 | 
						return p.httpPostOrPatch(http.MethodPatch, apiURLString+configPath, buf)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//SetConfig sets Patroni options via Patroni patch API call.
 | 
				
			||||||
 | 
					func (p *Patroni) SetConfig(server *v1.Pod, config map[string]interface{}) error {
 | 
				
			||||||
 | 
						buf := &bytes.Buffer{}
 | 
				
			||||||
 | 
						err := json.NewEncoder(buf).Encode(config)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return fmt.Errorf("could not encode json: %v", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						apiURLString, err := apiURL(server)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return p.httpPostOrPatch(http.MethodPatch, apiURLString+configPath, buf)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// MemberDataPatroni child element
 | 
					// MemberDataPatroni child element
 | 
				
			||||||
type MemberDataPatroni struct {
 | 
					type MemberDataPatroni struct {
 | 
				
			||||||
	Version string `json:"version"`
 | 
						Version string `json:"version"`
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue