Merge branch 'fix/graceful-shutdown' into feature/diagnostic-rest-api
# Conflicts: # pkg/controller/controller.go # pkg/controller/pod.go # pkg/controller/postgresql.go
This commit is contained in:
commit
54defa8070
|
|
@ -5,7 +5,7 @@ import (
|
|||
"sync"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/client-go/pkg/api/v1"
|
||||
"k8s.io/client-go/rest"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
|
|
@ -14,21 +14,26 @@ 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/teams"
|
||||
"github.com/zalando-incubator/postgres-operator/pkg/util/k8sutil"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
RestConfig *rest.Config
|
||||
KubeClient *kubernetes.Clientset
|
||||
RestClient *rest.RESTClient
|
||||
TeamsAPIClient *teams.API
|
||||
InfrastructureRoles map[string]spec.PgUser
|
||||
|
||||
NoDatabaseAccess bool
|
||||
NoTeamsAPI bool
|
||||
ConfigMapName spec.NamespacedName
|
||||
Namespace string
|
||||
}
|
||||
|
||||
type Controller struct {
|
||||
Config
|
||||
config Config
|
||||
opConfig *config.Config
|
||||
logger *logrus.Entry
|
||||
|
||||
logger *logrus.Entry
|
||||
KubeClient k8sutil.KubernetesClient
|
||||
RestClient rest.Interface // kubernetes API group REST client
|
||||
|
||||
clustersMu sync.RWMutex
|
||||
clusters map[spec.NamespacedName]*cluster.Cluster
|
||||
|
|
@ -38,23 +43,16 @@ type Controller struct {
|
|||
podInformer cache.SharedIndexInformer
|
||||
podCh chan spec.PodEvent
|
||||
|
||||
clusterEventQueues []*cache.FIFO
|
||||
|
||||
clusterEventQueues []*cache.FIFO
|
||||
lastClusterSyncTime int64
|
||||
}
|
||||
|
||||
func New(controllerConfig *Config, operatorConfig *config.Config) *Controller {
|
||||
func NewController(controllerConfig *Config) *Controller {
|
||||
logger := logrus.New()
|
||||
|
||||
if operatorConfig.DebugLogging {
|
||||
logger.Level = logrus.DebugLevel
|
||||
}
|
||||
|
||||
controllerConfig.TeamsAPIClient = teams.NewTeamsAPI(operatorConfig.TeamsAPIUrl, logger)
|
||||
|
||||
return &Controller{
|
||||
Config: *controllerConfig,
|
||||
opConfig: operatorConfig,
|
||||
config: *controllerConfig,
|
||||
opConfig: &config.Config{},
|
||||
logger: logger.WithField("pkg", "controller"),
|
||||
clusters: make(map[spec.NamespacedName]*cluster.Cluster),
|
||||
stopChs: make(map[spec.NamespacedName]chan struct{}),
|
||||
|
|
@ -62,54 +60,82 @@ func New(controllerConfig *Config, operatorConfig *config.Config) *Controller {
|
|||
}
|
||||
}
|
||||
|
||||
func (c *Controller) Run(stopCh <-chan struct{}, wg *sync.WaitGroup) {
|
||||
defer wg.Done()
|
||||
wg.Add(1)
|
||||
func (c *Controller) initClients() {
|
||||
client, err := k8sutil.ClientSet(c.config.RestConfig)
|
||||
if err != nil {
|
||||
c.logger.Fatalf("couldn't create client: %v", err)
|
||||
}
|
||||
c.KubeClient = k8sutil.NewFromKubernetesInterface(client)
|
||||
|
||||
c.initController()
|
||||
c.RestClient, err = k8sutil.KubernetesRestClient(*c.config.RestConfig)
|
||||
if err != nil {
|
||||
c.logger.Fatalf("couldn't create rest client: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
go c.runPodInformer(stopCh, wg)
|
||||
go c.runPostgresqlInformer(stopCh, wg)
|
||||
go c.podEventsDispatcher(stopCh, wg)
|
||||
go c.clusterResync(stopCh, wg)
|
||||
go c.restAPIServer(stopCh, wg)
|
||||
func (c *Controller) initOperatorConfig() {
|
||||
configMapData := make(map[string]string)
|
||||
|
||||
for i := range c.clusterEventQueues {
|
||||
go c.processClusterEventsQueue(stopCh, i, wg)
|
||||
if c.config.ConfigMapName != (spec.NamespacedName{}) {
|
||||
configMap, err := c.KubeClient.ConfigMaps(c.config.ConfigMapName.Namespace).
|
||||
Get(c.config.ConfigMapName.Name, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
configMapData = configMap.Data
|
||||
} else {
|
||||
c.logger.Infoln("No ConfigMap specified. Loading default values")
|
||||
}
|
||||
|
||||
c.logger.Info("Started working in background")
|
||||
if configMapData["namespace"] == "" { // Namespace in ConfigMap has priority over env var
|
||||
configMapData["namespace"] = c.config.Namespace
|
||||
}
|
||||
if c.config.NoDatabaseAccess {
|
||||
configMapData["enable_database_access"] = "false"
|
||||
}
|
||||
if c.config.NoTeamsAPI {
|
||||
configMapData["enable_teams_api"] = "false"
|
||||
}
|
||||
|
||||
c.opConfig = config.NewFromMap(configMapData)
|
||||
}
|
||||
|
||||
func (c *Controller) initController() {
|
||||
c.initClients()
|
||||
c.initOperatorConfig()
|
||||
|
||||
c.logger.Infof("Config: %s", c.opConfig.MustMarshal())
|
||||
|
||||
if c.opConfig.DebugLogging {
|
||||
c.logger.Level = logrus.DebugLevel
|
||||
}
|
||||
|
||||
if err := c.createTPR(); err != nil {
|
||||
c.logger.Fatalf("could not register ThirdPartyResource: %v", err)
|
||||
}
|
||||
|
||||
if infraRoles, err := c.getInfrastructureRoles(); err != nil {
|
||||
if infraRoles, err := c.getInfrastructureRoles(&c.opConfig.InfrastructureRolesSecretName); err != nil {
|
||||
c.logger.Warningf("could not get infrastructure roles: %v", err)
|
||||
} else {
|
||||
c.InfrastructureRoles = infraRoles
|
||||
c.config.InfrastructureRoles = infraRoles
|
||||
}
|
||||
|
||||
// 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{})
|
||||
|
||||
if err := c.postgresqlInformer.AddEventHandler(cache.ResourceEventHandlerFuncs{
|
||||
c.postgresqlInformer.AddEventHandler(cache.ResourceEventHandlerFuncs{
|
||||
AddFunc: c.postgresqlAdd,
|
||||
UpdateFunc: c.postgresqlUpdate,
|
||||
DeleteFunc: c.postgresqlDelete,
|
||||
}); err != nil {
|
||||
c.logger.Fatalf("could not add event handlers: %v", err)
|
||||
}
|
||||
})
|
||||
|
||||
// Pods
|
||||
podLw := &cache.ListWatch{
|
||||
|
|
@ -123,13 +149,11 @@ func (c *Controller) initController() {
|
|||
constants.QueueResyncPeriodPod,
|
||||
cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc})
|
||||
|
||||
if err := c.podInformer.AddEventHandler(cache.ResourceEventHandlerFuncs{
|
||||
c.podInformer.AddEventHandler(cache.ResourceEventHandlerFuncs{
|
||||
AddFunc: c.podAdd,
|
||||
UpdateFunc: c.podUpdate,
|
||||
DeleteFunc: c.podDelete,
|
||||
}); err != nil {
|
||||
c.logger.Fatalf("could not add event handlers: %v", err)
|
||||
}
|
||||
})
|
||||
|
||||
c.clusterEventQueues = make([]*cache.FIFO, c.opConfig.Workers)
|
||||
for i := range c.clusterEventQueues {
|
||||
|
|
@ -144,20 +168,31 @@ func (c *Controller) initController() {
|
|||
}
|
||||
}
|
||||
|
||||
func (c *Controller) Run(stopCh <-chan struct{}, wg *sync.WaitGroup) {
|
||||
c.initController()
|
||||
|
||||
wg.Add(4)
|
||||
go c.runPodInformer(stopCh, wg)
|
||||
go c.runPostgresqlInformer(stopCh, wg)
|
||||
go c.podEventsDispatcher(stopCh, wg)
|
||||
go c.clusterResync(stopCh, wg)
|
||||
|
||||
for i := range c.clusterEventQueues {
|
||||
wg.Add(1)
|
||||
go c.processClusterEventsQueue(i, stopCh, wg)
|
||||
}
|
||||
|
||||
c.logger.Info("Started working in background")
|
||||
}
|
||||
|
||||
func (c *Controller) runPodInformer(stopCh <-chan struct{}, wg *sync.WaitGroup) {
|
||||
defer wg.Done()
|
||||
wg.Add(1)
|
||||
|
||||
go c.podInformer.Run(stopCh)
|
||||
|
||||
<-stopCh
|
||||
c.podInformer.Run(stopCh)
|
||||
}
|
||||
|
||||
func (c *Controller) runPostgresqlInformer(stopCh <-chan struct{}, wg *sync.WaitGroup) {
|
||||
defer wg.Done()
|
||||
wg.Add(1)
|
||||
|
||||
go c.postgresqlInformer.Run(stopCh)
|
||||
|
||||
<-stopCh
|
||||
c.postgresqlInformer.Run(stopCh)
|
||||
}
|
||||
|
|
@ -101,7 +101,6 @@ func (c *Controller) podDelete(obj interface{}) {
|
|||
|
||||
func (c *Controller) podEventsDispatcher(stopCh <-chan struct{}, wg *sync.WaitGroup) {
|
||||
defer wg.Done()
|
||||
wg.Add(1)
|
||||
|
||||
c.logger.Debugln("Watching all pod events")
|
||||
for {
|
||||
|
|
|
|||
|
|
@ -22,7 +22,6 @@ import (
|
|||
|
||||
func (c *Controller) clusterResync(stopCh <-chan struct{}, wg *sync.WaitGroup) {
|
||||
defer wg.Done()
|
||||
wg.Add(1)
|
||||
ticker := time.NewTicker(c.opConfig.ResyncPeriod)
|
||||
|
||||
for {
|
||||
|
|
@ -229,9 +228,8 @@ func (c *Controller) processEvent(obj interface{}) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (c *Controller) processClusterEventsQueue(stopCh <-chan struct{}, idx int, wg *sync.WaitGroup) {
|
||||
func (c *Controller) processClusterEventsQueue(idx int, stopCh <-chan struct{}, wg *sync.WaitGroup) {
|
||||
defer wg.Done()
|
||||
wg.Add(1)
|
||||
|
||||
go func() {
|
||||
if _, err := c.clusterEventQueues[idx].Pop(cache.PopProcessFunc(c.processEvent)); err != nil {
|
||||
|
|
|
|||
Loading…
Reference in New Issue