resolve conflicts

This commit is contained in:
Sergey Dudoladov
2020-04-30 09:50:45 +02:00
51 changed files with 2129 additions and 429 deletions
+10 -6
View File
@@ -9,6 +9,7 @@ import (
"github.com/zalando/postgres-operator/pkg/spec"
"github.com/zalando/postgres-operator/pkg/util/constants"
v1 "k8s.io/api/core/v1"
)
// CRD describes CustomResourceDefinition specific configuration parameters
@@ -107,12 +108,14 @@ type Config struct {
LogicalBackup
ConnectionPooler
WatchedNamespace string `name:"watched_namespace"` // special values: "*" means 'watch all namespaces', the empty string "" means 'watch a namespace where operator is deployed to'
KubernetesUseConfigMaps bool `name:"kubernetes_use_configmaps" default:"false"`
EtcdHost string `name:"etcd_host" default:""` // special values: the empty string "" means Patroni will use K8s as a DCS
DockerImage string `name:"docker_image" default:"registry.opensource.zalan.do/acid/spilo-12:1.6-p2"`
Sidecars map[string]string `name:"sidecar_docker_images"`
PodServiceAccountName string `name:"pod_service_account_name" default:"postgres-pod"`
WatchedNamespace string `name:"watched_namespace"` // special values: "*" means 'watch all namespaces', the empty string "" means 'watch a namespace where operator is deployed to'
KubernetesUseConfigMaps bool `name:"kubernetes_use_configmaps" default:"false"`
EtcdHost string `name:"etcd_host" default:""` // special values: the empty string "" means Patroni will use K8s as a DCS
DockerImage string `name:"docker_image" default:"registry.opensource.zalan.do/acid/spilo-cdp-12:1.6-p115"`
// deprecated in favour of SidecarContainers
SidecarImages map[string]string `name:"sidecar_docker_images"`
SidecarContainers []v1.Container `name:"sidecars"`
PodServiceAccountName string `name:"pod_service_account_name" default:"postgres-pod"`
// value of this string must be valid JSON or YAML; see initPodServiceAccount
PodServiceAccountDefinition string `name:"pod_service_account_definition" default:""`
PodServiceAccountRoleBindingDefinition string `name:"pod_service_account_role_binding_definition" default:""`
@@ -155,6 +158,7 @@ type Config struct {
PostgresSuperuserTeams []string `name:"postgres_superuser_teams" default:""`
SetMemoryRequestToLimit bool `name:"set_memory_request_to_limit" default:"false"`
EnableUnusedPVCDeletion bool `name:"enable_unused_pvc_deletion" default:"false"`
EnableLazySpiloUpgrade bool `name:"enable_lazy_spilo_upgrade" default:"false"`
}
// MustMarshal marshals the config or panics
+4
View File
@@ -14,4 +14,8 @@ const (
RoleFlagCreateDB = "CREATEDB"
RoleFlagReplication = "REPLICATION"
RoleFlagByPassRLS = "BYPASSRLS"
OwnerRoleNameSuffix = "_owner"
ReaderRoleNameSuffix = "_reader"
WriterRoleNameSuffix = "_writer"
UserRoleNameSuffix = "_user"
)
+2
View File
@@ -45,6 +45,7 @@ type KubernetesClient struct {
corev1.NodesGetter
corev1.NamespacesGetter
corev1.ServiceAccountsGetter
corev1.EventsGetter
appsv1.StatefulSetsGetter
appsv1.DeploymentsGetter
rbacv1.RoleBindingsGetter
@@ -142,6 +143,7 @@ func NewFromConfig(cfg *rest.Config) (KubernetesClient, error) {
kubeClient.RESTClient = client.CoreV1().RESTClient()
kubeClient.RoleBindingsGetter = client.RbacV1()
kubeClient.CronJobsGetter = client.BatchV1beta1()
kubeClient.EventsGetter = client.CoreV1()
apiextClient, err := apiextclient.NewForConfig(cfg)
if err != nil {
+36 -1
View File
@@ -3,6 +3,7 @@ package patroni
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"io/ioutil"
"net"
@@ -11,7 +12,7 @@ import (
"time"
"github.com/sirupsen/logrus"
"k8s.io/api/core/v1"
v1 "k8s.io/api/core/v1"
)
const (
@@ -25,6 +26,7 @@ const (
type Interface interface {
Switchover(master *v1.Pod, candidate string) error
SetPostgresParameters(server *v1.Pod, options map[string]string) error
GetPatroniMemberState(pod *v1.Pod) (string, error)
}
// Patroni API client
@@ -123,3 +125,36 @@ func (p *Patroni) SetPostgresParameters(server *v1.Pod, parameters map[string]st
}
return p.httpPostOrPatch(http.MethodPatch, apiURLString+configPath, buf)
}
//GetPatroniMemberState returns a state of member of a Patroni cluster
func (p *Patroni) GetPatroniMemberState(server *v1.Pod) (string, error) {
apiURLString, err := apiURL(server)
if err != nil {
return "", err
}
response, err := p.httpClient.Get(apiURLString)
if err != nil {
return "", fmt.Errorf("could not perform Get request: %v", err)
}
defer response.Body.Close()
body, err := ioutil.ReadAll(response.Body)
if err != nil {
return "", fmt.Errorf("could not read response: %v", err)
}
data := make(map[string]interface{})
err = json.Unmarshal(body, &data)
if err != nil {
return "", err
}
state, ok := data["state"].(string)
if !ok {
return "", errors.New("Patroni Get call response contains wrong type for 'state' field")
}
return state, nil
}
+28 -10
View File
@@ -73,26 +73,44 @@ func (strategy DefaultUserSyncStrategy) ProduceSyncRequests(dbUsers spec.PgUserM
}
// ExecuteSyncRequests makes actual database changes from the requests passed in its arguments.
func (strategy DefaultUserSyncStrategy) ExecuteSyncRequests(reqs []spec.PgSyncUserRequest, db *sql.DB) error {
for _, r := range reqs {
switch r.Kind {
func (strategy DefaultUserSyncStrategy) ExecuteSyncRequests(requests []spec.PgSyncUserRequest, db *sql.DB) error {
var reqretries []spec.PgSyncUserRequest
var errors []string
for _, request := range requests {
switch request.Kind {
case spec.PGSyncUserAdd:
if err := strategy.createPgUser(r.User, db); err != nil {
return fmt.Errorf("could not create user %q: %v", r.User.Name, err)
if err := strategy.createPgUser(request.User, db); err != nil {
reqretries = append(reqretries, request)
errors = append(errors, fmt.Sprintf("could not create user %q: %v", request.User.Name, err))
}
case spec.PGsyncUserAlter:
if err := strategy.alterPgUser(r.User, db); err != nil {
return fmt.Errorf("could not alter user %q: %v", r.User.Name, err)
if err := strategy.alterPgUser(request.User, db); err != nil {
reqretries = append(reqretries, request)
errors = append(errors, fmt.Sprintf("could not alter user %q: %v", request.User.Name, err))
}
case spec.PGSyncAlterSet:
if err := strategy.alterPgUserSet(r.User, db); err != nil {
return fmt.Errorf("could not set custom user %q parameters: %v", r.User.Name, err)
if err := strategy.alterPgUserSet(request.User, db); err != nil {
reqretries = append(reqretries, request)
errors = append(errors, fmt.Sprintf("could not set custom user %q parameters: %v", request.User.Name, err))
}
default:
return fmt.Errorf("unrecognized operation: %v", r.Kind)
return fmt.Errorf("unrecognized operation: %v", request.Kind)
}
}
// creating roles might fail if group role members are created before the parent role
// retry adding roles as long as the number of failed attempts is shrinking
if len(reqretries) > 0 {
if len(reqretries) < len(requests) {
if err := strategy.ExecuteSyncRequests(reqretries, db); err != nil {
return err
}
} else {
return fmt.Errorf("could not execute sync requests for users: %v", errors)
}
}
return nil
}
func (strategy DefaultUserSyncStrategy) alterPgUserSet(user spec.PgUser, db *sql.DB) (err error) {