mirror of
https://github.com/zalando/postgres-operator.git
synced 2026-10-08 23:06:45 +02:00
refactor
This commit is contained in:
@@ -5,6 +5,7 @@ import (
|
||||
"sync"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/pkg/api/v1"
|
||||
"k8s.io/client-go/rest"
|
||||
@@ -14,15 +15,18 @@ import (
|
||||
"github.com/zalando-incubator/postgres-operator/pkg/spec"
|
||||
"github.com/zalando-incubator/postgres-operator/pkg/util/config"
|
||||
"github.com/zalando-incubator/postgres-operator/pkg/util/constants"
|
||||
"github.com/zalando-incubator/postgres-operator/pkg/util/k8sutil"
|
||||
"github.com/zalando-incubator/postgres-operator/pkg/util/teams"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
RestConfig *rest.Config
|
||||
KubeClient *kubernetes.Clientset
|
||||
RestClient rest.Interface
|
||||
TeamsAPIClient *teams.API
|
||||
InfrastructureRoles map[string]spec.PgUser
|
||||
|
||||
NoDatabaseAccess bool
|
||||
NoTeamsAPI bool
|
||||
ConfigMapName spec.NamespacedName
|
||||
Namespace string
|
||||
}
|
||||
|
||||
type Controller struct {
|
||||
@@ -30,6 +34,10 @@ type Controller struct {
|
||||
opConfig *config.Config
|
||||
logger *logrus.Entry
|
||||
|
||||
KubeClient *kubernetes.Clientset
|
||||
RestClient rest.Interface
|
||||
TeamsAPIClient *teams.API
|
||||
|
||||
clustersMu sync.RWMutex
|
||||
clusters map[spec.NamespacedName]*cluster.Cluster
|
||||
stopChs map[spec.NamespacedName]chan struct{}
|
||||
@@ -43,22 +51,58 @@ type Controller struct {
|
||||
lastClusterSyncTime int64
|
||||
}
|
||||
|
||||
func New(controllerConfig *Config, operatorConfig *config.Config) *Controller {
|
||||
func New(controllerConfig *Config) *Controller {
|
||||
configMapData := make(map[string]string)
|
||||
logger := logrus.New()
|
||||
|
||||
client, err := k8sutil.KubernetesClient(controllerConfig.RestConfig)
|
||||
if err != nil {
|
||||
logger.Fatalf("couldn't create client: %v", err)
|
||||
}
|
||||
|
||||
restClient, err := k8sutil.KubernetesRestClient(*controllerConfig.RestConfig)
|
||||
if err != nil {
|
||||
logger.Fatalf("couldn't create rest client: %v", err)
|
||||
}
|
||||
|
||||
if controllerConfig.ConfigMapName != (spec.NamespacedName{}) {
|
||||
configMap, err := client.ConfigMaps(controllerConfig.ConfigMapName.Namespace).Get(controllerConfig.ConfigMapName.Name, meta_v1.GetOptions{})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
configMapData = configMap.Data
|
||||
} else {
|
||||
logger.Infoln("No ConfigMap specified. Loading default values")
|
||||
}
|
||||
|
||||
if configMapData["namespace"] == "" { // Namespace in ConfigMap has priority over env var
|
||||
configMapData["namespace"] = controllerConfig.Namespace
|
||||
}
|
||||
if controllerConfig.NoDatabaseAccess {
|
||||
configMapData["enable_database_access"] = "false"
|
||||
}
|
||||
if controllerConfig.NoTeamsAPI {
|
||||
configMapData["enable_teams_api"] = "false"
|
||||
}
|
||||
operatorConfig := config.NewFromMap(configMapData)
|
||||
|
||||
logger.Infof("Config: %s", operatorConfig.MustMarshal())
|
||||
|
||||
if operatorConfig.DebugLogging {
|
||||
logger.Level = logrus.DebugLevel
|
||||
}
|
||||
|
||||
controllerConfig.TeamsAPIClient = teams.NewTeamsAPI(operatorConfig.TeamsAPIUrl, logger)
|
||||
|
||||
return &Controller{
|
||||
Config: *controllerConfig,
|
||||
opConfig: operatorConfig,
|
||||
logger: logger.WithField("pkg", "controller"),
|
||||
clusters: make(map[spec.NamespacedName]*cluster.Cluster),
|
||||
stopChs: make(map[spec.NamespacedName]chan struct{}),
|
||||
podCh: make(chan spec.PodEvent),
|
||||
Config: *controllerConfig,
|
||||
opConfig: operatorConfig,
|
||||
logger: logger.WithField("pkg", "controller"),
|
||||
clusters: make(map[spec.NamespacedName]*cluster.Cluster),
|
||||
stopChs: make(map[spec.NamespacedName]chan struct{}),
|
||||
podCh: make(chan spec.PodEvent),
|
||||
TeamsAPIClient: teams.NewTeamsAPI(operatorConfig.TeamsAPIUrl, logger),
|
||||
KubeClient: client,
|
||||
RestClient: restClient,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -89,15 +133,14 @@ func (c *Controller) initController() {
|
||||
}
|
||||
|
||||
// Postgresqls
|
||||
clusterLw := &cache.ListWatch{
|
||||
ListFunc: c.clusterListFunc,
|
||||
WatchFunc: c.clusterWatchFunc,
|
||||
}
|
||||
c.postgresqlInformer = cache.NewSharedIndexInformer(
|
||||
clusterLw,
|
||||
&cache.ListWatch{
|
||||
ListFunc: c.clusterListFunc,
|
||||
WatchFunc: c.clusterWatchFunc,
|
||||
},
|
||||
&spec.Postgresql{},
|
||||
constants.QueueResyncPeriodTPR,
|
||||
cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc})
|
||||
cache.Indexers{})
|
||||
|
||||
c.postgresqlInformer.AddEventHandler(cache.ResourceEventHandlerFuncs{
|
||||
AddFunc: c.postgresqlAdd,
|
||||
|
||||
@@ -3,18 +3,15 @@ package controller
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"k8s.io/apimachinery/pkg/api/meta"
|
||||
meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/fields"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/apimachinery/pkg/watch"
|
||||
"k8s.io/client-go/kubernetes/scheme"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
|
||||
"encoding/json"
|
||||
"github.com/zalando-incubator/postgres-operator/pkg/cluster"
|
||||
"github.com/zalando-incubator/postgres-operator/pkg/spec"
|
||||
"github.com/zalando-incubator/postgres-operator/pkg/util"
|
||||
@@ -35,67 +32,60 @@ func (c *Controller) clusterResync(stopCh <-chan struct{}) {
|
||||
}
|
||||
|
||||
func (c *Controller) clusterListFunc(options meta_v1.ListOptions) (runtime.Object, error) {
|
||||
c.logger.Info("Getting list of currently running clusters")
|
||||
|
||||
req := c.RestClient.Get().
|
||||
RequestURI(fmt.Sprintf(constants.ListClustersURITemplate, c.opConfig.Namespace)).
|
||||
VersionedParams(&options, scheme.ParameterCodec).
|
||||
FieldsSelectorParam(fields.Everything())
|
||||
|
||||
object, err := req.Do().Get()
|
||||
req := c.RestClient.
|
||||
Get().
|
||||
Namespace(c.opConfig.Namespace).
|
||||
Resource(constants.ResourceName).
|
||||
VersionedParams(&options, meta_v1.ParameterCodec)
|
||||
|
||||
b, err := req.DoRaw()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not get list of postgresql objects: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
var list spec.PostgresqlList
|
||||
|
||||
return &list, json.Unmarshal(b, &list)
|
||||
}
|
||||
|
||||
type tprDecoder struct {
|
||||
dec *json.Decoder
|
||||
close func() error
|
||||
}
|
||||
|
||||
func (d *tprDecoder) Close() {
|
||||
d.close()
|
||||
}
|
||||
|
||||
func (d *tprDecoder) Decode() (action watch.EventType, object runtime.Object, err error) {
|
||||
var e struct {
|
||||
Type watch.EventType
|
||||
Object spec.Postgresql
|
||||
}
|
||||
if err := d.dec.Decode(&e); err != nil {
|
||||
return watch.Error, nil, err
|
||||
}
|
||||
|
||||
objList, err := meta.ExtractList(object)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not extract list of postgresql objects: %v", err)
|
||||
}
|
||||
|
||||
if time.Now().Unix()-atomic.LoadInt64(&c.lastClusterSyncTime) <= int64(c.opConfig.ResyncPeriod.Seconds()) {
|
||||
c.logger.Debugln("skipping resync of clusters")
|
||||
return object, err
|
||||
}
|
||||
|
||||
var activeClustersCnt, failedClustersCnt int
|
||||
for _, obj := range objList {
|
||||
pg, ok := obj.(*spec.Postgresql)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("could not cast object to postgresql")
|
||||
}
|
||||
|
||||
if pg.Error != nil {
|
||||
failedClustersCnt++
|
||||
continue
|
||||
}
|
||||
c.queueClusterEvent(nil, pg, spec.EventSync)
|
||||
activeClustersCnt++
|
||||
}
|
||||
if len(objList) > 0 {
|
||||
if failedClustersCnt > 0 && activeClustersCnt == 0 {
|
||||
c.logger.Infof("There are no clusters running. %d are in the failed state", failedClustersCnt)
|
||||
} else if failedClustersCnt == 0 && activeClustersCnt > 0 {
|
||||
c.logger.Infof("There are %d clusters running", activeClustersCnt)
|
||||
} else {
|
||||
c.logger.Infof("There are %d clusters running and %d are in the failed state", activeClustersCnt, failedClustersCnt)
|
||||
}
|
||||
} else {
|
||||
c.logger.Infof("No clusters running")
|
||||
}
|
||||
|
||||
atomic.StoreInt64(&c.lastClusterSyncTime, time.Now().Unix())
|
||||
|
||||
return object, err
|
||||
return e.Type, &e.Object, nil
|
||||
}
|
||||
|
||||
func (c *Controller) clusterWatchFunc(options meta_v1.ListOptions) (watch.Interface, error) {
|
||||
options.Watch = true
|
||||
req := c.RestClient.Get().
|
||||
RequestURI(fmt.Sprintf(constants.ListClustersURITemplate, c.opConfig.Namespace)).
|
||||
VersionedParams(&options, scheme.ParameterCodec).
|
||||
FieldsSelectorParam(fields.Everything())
|
||||
return req.Watch()
|
||||
r, err := c.RestClient.
|
||||
Get().
|
||||
Namespace(c.opConfig.Namespace).
|
||||
Resource(constants.ResourceName).
|
||||
VersionedParams(&options, meta_v1.ParameterCodec).
|
||||
FieldsSelectorParam(nil).
|
||||
Stream()
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return watch.NewStreamWatcher(&tprDecoder{
|
||||
dec: json.NewDecoder(r),
|
||||
close: r.Close,
|
||||
}), nil
|
||||
}
|
||||
|
||||
func (c *Controller) processEvent(obj interface{}) error {
|
||||
@@ -127,7 +117,7 @@ func (c *Controller) processEvent(obj interface{}) error {
|
||||
logger.Infof("Creation of the %q cluster started", clusterName)
|
||||
|
||||
stopCh := make(chan struct{})
|
||||
cl = cluster.New(c.makeClusterConfig(), *event.NewSpec, logger)
|
||||
cl = cluster.New(c.makeClusterConfig(), c.KubeClient, *event.NewSpec, logger)
|
||||
cl.Run(stopCh)
|
||||
|
||||
c.clustersMu.Lock()
|
||||
@@ -183,7 +173,7 @@ func (c *Controller) processEvent(obj interface{}) error {
|
||||
// no race condition because a cluster is always processed by single worker
|
||||
if !clusterFound {
|
||||
stopCh := make(chan struct{})
|
||||
cl = cluster.New(c.makeClusterConfig(), *event.NewSpec, logger)
|
||||
cl = cluster.New(c.makeClusterConfig(), c.KubeClient, *event.NewSpec, logger)
|
||||
cl.Run(stopCh)
|
||||
|
||||
c.clustersMu.Lock()
|
||||
|
||||
@@ -22,10 +22,7 @@ func (c *Controller) makeClusterConfig() cluster.Config {
|
||||
}
|
||||
|
||||
return cluster.Config{
|
||||
KubeClient: c.KubeClient,
|
||||
RestClient: c.RestClient,
|
||||
RestConfig: c.RestConfig,
|
||||
TeamsAPIClient: c.TeamsAPIClient,
|
||||
OpConfig: config.Copy(c.opConfig),
|
||||
InfrastructureRoles: infrastructureRoles,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user