From 8f8d3d514822aa558bf6ecb3b98476f1706bbed1 Mon Sep 17 00:00:00 2001 From: Murat Kabilov <murat.kabilov@zalando.de> Date: Fri, 9 Jun 2017 17:31:45 +0200 Subject: [PATCH] move types from spec into separate package --- cmd/main.go | 6 ++-- pkg/cluster/cluster.go | 50 +++++++++++++------------------ pkg/cluster/filesystems.go | 6 ++-- pkg/cluster/k8sres.go | 3 +- pkg/cluster/pg.go | 8 ++--- pkg/cluster/pod.go | 10 +++---- pkg/cluster/resources.go | 4 +-- pkg/cluster/util.go | 9 +++--- pkg/cluster/volumes.go | 5 ++-- pkg/controller/controller.go | 18 +++++------ pkg/controller/pod.go | 14 ++++----- pkg/controller/postgresql.go | 39 ++++++++++++------------ pkg/controller/util.go | 20 ++++++------- pkg/types/namespacedname.go | 41 +++++++++++++++++++++++++ pkg/{spec => types}/types.go | 49 +++++++++--------------------- pkg/{spec => types}/types_test.go | 2 +- pkg/util/config/config.go | 16 +++++----- pkg/util/users/users.go | 34 ++++++++++----------- pkg/util/util.go | 8 ++--- pkg/util/util_test.go | 8 ++--- 20 files changed, 182 insertions(+), 168 deletions(-) create mode 100644 pkg/types/namespacedname.go rename pkg/{spec => types}/types.go (61%) rename pkg/{spec => types}/types_test.go (98%) diff --git a/cmd/main.go b/cmd/main.go index 2d53f4b8..404f35ec 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -9,7 +9,7 @@ import ( "syscall" "github.com/zalando-incubator/postgres-operator/pkg/controller" - "github.com/zalando-incubator/postgres-operator/pkg/spec" + "github.com/zalando-incubator/postgres-operator/pkg/types" "github.com/zalando-incubator/postgres-operator/pkg/util/config" "github.com/zalando-incubator/postgres-operator/pkg/util/k8sutil" ) @@ -17,7 +17,7 @@ import ( var ( KubeConfigFile string podNamespace string - configMapName spec.NamespacedName + configMapName types.NamespacedName OutOfCluster bool noTeamsAPI bool noDatabaseAccess bool @@ -78,7 +78,7 @@ func main() { controllerConfig := ControllerConfig() - if configMapName != (spec.NamespacedName{}) { + if configMapName != (types.NamespacedName{}) { configMap, err := controllerConfig.KubeClient.ConfigMaps(configMapName.Namespace).Get(configMapName.Name) if err != nil { panic(err) diff --git a/pkg/cluster/cluster.go b/pkg/cluster/cluster.go index fa307b96..c9195346 100644 --- a/pkg/cluster/cluster.go +++ b/pkg/cluster/cluster.go @@ -14,11 +14,12 @@ import ( "k8s.io/client-go/pkg/api" "k8s.io/client-go/pkg/api/v1" "k8s.io/client-go/pkg/apis/apps/v1beta1" - "k8s.io/client-go/pkg/types" + ktypes "k8s.io/client-go/pkg/types" "k8s.io/client-go/rest" "k8s.io/client-go/tools/cache" "github.com/zalando-incubator/postgres-operator/pkg/spec" + "github.com/zalando-incubator/postgres-operator/pkg/types" "github.com/zalando-incubator/postgres-operator/pkg/util" "github.com/zalando-incubator/postgres-operator/pkg/util/config" "github.com/zalando-incubator/postgres-operator/pkg/util/constants" @@ -28,17 +29,6 @@ import ( "github.com/zalando-incubator/postgres-operator/pkg/util/volumes" ) -type Interface interface { - Create() error - Delete() error - ExecCommand(podName *spec.NamespacedName, command ...string) (string, error) - ReceivePodEvent(event spec.PodEvent) - Run(stopCh <-chan struct{}) - Sync() error - Update(newSpec *spec.Postgresql) error - SetFailed(err error) -} - type PostgresRole string const ( @@ -53,13 +43,13 @@ type Config struct { RestConfig *rest.Config TeamsAPIClient *teams.API OpConfig config.Config - InfrastructureRoles map[string]spec.PgUser // inherited from the controller + InfrastructureRoles map[string]types.PgUser // inherited from the controller } type kubeResources struct { Service map[PostgresRole]*v1.Service Endpoint *v1.Endpoints - Secrets map[types.UID]*v1.Secret + Secrets map[ktypes.UID]*v1.Secret Statefulset *v1beta1.StatefulSet //Pods are treated separately //PVCs are treated separately @@ -70,14 +60,14 @@ type Cluster struct { spec.Postgresql Config logger *logrus.Entry - pgUsers map[string]spec.PgUser - systemUsers map[string]spec.PgUser - podSubscribers map[spec.NamespacedName]chan spec.PodEvent + pgUsers map[string]types.PgUser + systemUsers map[string]types.PgUser + podSubscribers map[types.NamespacedName]chan types.PodEvent podSubscribersMu sync.RWMutex pgDb *sql.DB mu sync.Mutex masterLess bool - userSyncStrategy spec.UserSyncer + userSyncStrategy types.UserSyncer deleteOptions *v1.DeleteOptions podEventsQueue *cache.FIFO } @@ -92,11 +82,11 @@ type compareStatefulsetResult struct { // New creates a new cluster. This function should be called from a controller. func New(cfg Config, pgSpec spec.Postgresql, logger *logrus.Entry) *Cluster { lg := logger.WithField("pkg", "cluster").WithField("cluster-name", pgSpec.Metadata.Name) - kubeResources := kubeResources{Secrets: make(map[types.UID]*v1.Secret), Service: make(map[PostgresRole]*v1.Service)} + kubeResources := kubeResources{Secrets: make(map[ktypes.UID]*v1.Secret), Service: make(map[PostgresRole]*v1.Service)} orphanDependents := true podEventsQueue := cache.NewFIFO(func(obj interface{}) (string, error) { - e, ok := obj.(spec.PodEvent) + e, ok := obj.(types.PodEvent) if !ok { return "", fmt.Errorf("could not cast to PodEvent") } @@ -108,9 +98,9 @@ func New(cfg Config, pgSpec spec.Postgresql, logger *logrus.Entry) *Cluster { Config: cfg, Postgresql: pgSpec, logger: lg, - pgUsers: make(map[string]spec.PgUser), - systemUsers: make(map[string]spec.PgUser), - podSubscribers: make(map[spec.NamespacedName]chan spec.PodEvent), + pgUsers: make(map[string]types.PgUser), + systemUsers: make(map[string]types.PgUser), + podSubscribers: make(map[types.NamespacedName]chan types.PodEvent), kubeResources: kubeResources, masterLess: false, userSyncStrategy: users.DefaultUserSyncStrategy{}, @@ -121,7 +111,7 @@ func New(cfg Config, pgSpec spec.Postgresql, logger *logrus.Entry) *Cluster { return cluster } -func (c *Cluster) clusterName() spec.NamespacedName { +func (c *Cluster) clusterName() types.NamespacedName { return util.NameFromMeta(c.Metadata) } @@ -543,14 +533,14 @@ func (c *Cluster) Delete() error { } // ReceivePodEvent is called back by the controller in order to add the cluster's pod event to the queue. -func (c *Cluster) ReceivePodEvent(event spec.PodEvent) { +func (c *Cluster) ReceivePodEvent(event types.PodEvent) { if err := c.podEventsQueue.Add(event); err != nil { c.logger.Errorf("error when receiving pod events: %v", err) } } func (c *Cluster) processPodEvent(obj interface{}) error { - event, ok := obj.(spec.PodEvent) + event, ok := obj.(types.PodEvent) if !ok { return fmt.Errorf("could not cast to PodEvent") } @@ -588,11 +578,11 @@ func (c *Cluster) initSystemUsers() { // task to Patroni. Those definitions are only used to create // secrets, therefore, setting flags like SUPERUSER or REPLICATION // is not necessary here - c.systemUsers[constants.SuperuserKeyName] = spec.PgUser{ + c.systemUsers[constants.SuperuserKeyName] = types.PgUser{ Name: c.OpConfig.SuperUsername, Password: util.RandomPassword(constants.PasswordLength), } - c.systemUsers[constants.ReplicationUserKeyName] = spec.PgUser{ + c.systemUsers[constants.ReplicationUserKeyName] = types.PgUser{ Name: c.OpConfig.ReplicationUsername, Password: util.RandomPassword(constants.PasswordLength), } @@ -609,7 +599,7 @@ func (c *Cluster) initRobotUsers() error { return fmt.Errorf("invalid flags for user '%v': %v", username, err) } - c.pgUsers[username] = spec.PgUser{ + c.pgUsers[username] = types.PgUser{ Name: username, Password: util.RandomPassword(constants.PasswordLength), Flags: flags, @@ -627,7 +617,7 @@ func (c *Cluster) initHumanUsers() error { for _, username := range teamMembers { flags := []string{constants.RoleFlagLogin, constants.RoleFlagSuperuser} memberOf := []string{c.OpConfig.PamRoleName} - c.pgUsers[username] = spec.PgUser{Name: username, Flags: flags, MemberOf: memberOf} + c.pgUsers[username] = types.PgUser{Name: username, Flags: flags, MemberOf: memberOf} } return nil diff --git a/pkg/cluster/filesystems.go b/pkg/cluster/filesystems.go index e68e5614..73aff9d4 100644 --- a/pkg/cluster/filesystems.go +++ b/pkg/cluster/filesystems.go @@ -4,12 +4,12 @@ import ( "fmt" "strings" - "github.com/zalando-incubator/postgres-operator/pkg/spec" + "github.com/zalando-incubator/postgres-operator/pkg/types" "github.com/zalando-incubator/postgres-operator/pkg/util/constants" "github.com/zalando-incubator/postgres-operator/pkg/util/filesystems" ) -func (c *Cluster) getPostgresFilesystemInfo(podName *spec.NamespacedName) (device, fstype string, err error) { +func (c *Cluster) getPostgresFilesystemInfo(podName *types.NamespacedName) (device, fstype string, err error) { out, err := c.ExecCommand(podName, "bash", "-c", fmt.Sprintf("df -T %s|tail -1", constants.PostgresDataMount)) if err != nil { return "", "", err @@ -22,7 +22,7 @@ func (c *Cluster) getPostgresFilesystemInfo(podName *spec.NamespacedName) (devic return fields[0], fields[1], nil } -func (c *Cluster) resizePostgresFilesystem(podName *spec.NamespacedName, resizers []filesystems.FilesystemResizer) error { +func (c *Cluster) resizePostgresFilesystem(podName *types.NamespacedName, resizers []filesystems.FilesystemResizer) error { // resize2fs always writes to stderr, and ExecCommand considers a non-empty stderr an error // first, determine the device and the filesystem deviceName, fsType, err := c.getPostgresFilesystemInfo(podName) diff --git a/pkg/cluster/k8sres.go b/pkg/cluster/k8sres.go index fd71661a..bbcb49d8 100644 --- a/pkg/cluster/k8sres.go +++ b/pkg/cluster/k8sres.go @@ -11,6 +11,7 @@ import ( "k8s.io/client-go/pkg/util/intstr" "github.com/zalando-incubator/postgres-operator/pkg/spec" + "github.com/zalando-incubator/postgres-operator/pkg/types" "github.com/zalando-incubator/postgres-operator/pkg/util/constants" ) @@ -404,7 +405,7 @@ func (c *Cluster) genUserSecrets() (secrets map[string]*v1.Secret) { return } -func (c *Cluster) genSingleUserSecret(namespace string, pgUser spec.PgUser) *v1.Secret { +func (c *Cluster) genSingleUserSecret(namespace string, pgUser types.PgUser) *v1.Secret { //Skip users with no password i.e. human users (they'll be authenticated using pam) if pgUser.Password == "" { return nil diff --git a/pkg/cluster/pg.go b/pkg/cluster/pg.go index fd677006..50a11ef5 100644 --- a/pkg/cluster/pg.go +++ b/pkg/cluster/pg.go @@ -7,7 +7,7 @@ import ( "github.com/lib/pq" - "github.com/zalando-incubator/postgres-operator/pkg/spec" + "github.com/zalando-incubator/postgres-operator/pkg/types" "github.com/zalando-incubator/postgres-operator/pkg/util/constants" ) @@ -60,9 +60,9 @@ func (c *Cluster) initDbConn() (err error) { return nil } -func (c *Cluster) readPgUsersFromDatabase(userNames []string) (users spec.PgUserMap, err error) { +func (c *Cluster) readPgUsersFromDatabase(userNames []string) (users types.PgUserMap, err error) { var rows *sql.Rows - users = make(spec.PgUserMap) + users = make(types.PgUserMap) if rows, err = c.pgDb.Query(getUserSQL, pq.Array(userNames)); err != nil { return nil, fmt.Errorf("error when querying users: %v", err) } @@ -85,7 +85,7 @@ func (c *Cluster) readPgUsersFromDatabase(userNames []string) (users spec.PgUser } flags := makeUserFlags(rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlogin) // XXX: the code assumes the password we get from pg_authid is always MD5 - users[rolname] = spec.PgUser{Name: rolname, Password: rolpassword, Flags: flags, MemberOf: memberof} + users[rolname] = types.PgUser{Name: rolname, Password: rolpassword, Flags: flags, MemberOf: memberof} } return users, nil diff --git a/pkg/cluster/pod.go b/pkg/cluster/pod.go index 49497d92..7dfa6f59 100644 --- a/pkg/cluster/pod.go +++ b/pkg/cluster/pod.go @@ -5,7 +5,7 @@ import ( "k8s.io/client-go/pkg/api/v1" - "github.com/zalando-incubator/postgres-operator/pkg/spec" + "github.com/zalando-incubator/postgres-operator/pkg/types" "github.com/zalando-incubator/postgres-operator/pkg/util" "github.com/zalando-incubator/postgres-operator/pkg/util/constants" ) @@ -50,7 +50,7 @@ func (c *Cluster) deletePods() error { return nil } -func (c *Cluster) deletePod(podName spec.NamespacedName) error { +func (c *Cluster) deletePod(podName types.NamespacedName) error { ch := c.registerPodSubscriber(podName) defer c.unregisterPodSubscriber(podName) @@ -65,7 +65,7 @@ func (c *Cluster) deletePod(podName spec.NamespacedName) error { return nil } -func (c *Cluster) unregisterPodSubscriber(podName spec.NamespacedName) { +func (c *Cluster) unregisterPodSubscriber(podName types.NamespacedName) { c.podSubscribersMu.Lock() defer c.podSubscribersMu.Unlock() @@ -77,11 +77,11 @@ func (c *Cluster) unregisterPodSubscriber(podName spec.NamespacedName) { delete(c.podSubscribers, podName) } -func (c *Cluster) registerPodSubscriber(podName spec.NamespacedName) chan spec.PodEvent { +func (c *Cluster) registerPodSubscriber(podName types.NamespacedName) chan types.PodEvent { c.podSubscribersMu.Lock() defer c.podSubscribersMu.Unlock() - ch := make(chan spec.PodEvent) + ch := make(chan types.PodEvent) if _, ok := c.podSubscribers[podName]; ok { panic("pod '" + podName.String() + "' is already subscribed") } diff --git a/pkg/cluster/resources.go b/pkg/cluster/resources.go index aa596430..18a9ee25 100644 --- a/pkg/cluster/resources.go +++ b/pkg/cluster/resources.go @@ -7,7 +7,7 @@ import ( "k8s.io/client-go/pkg/api/v1" "k8s.io/client-go/pkg/apis/apps/v1beta1" - "github.com/zalando-incubator/postgres-operator/pkg/spec" + "github.com/zalando-incubator/postgres-operator/pkg/types" "github.com/zalando-incubator/postgres-operator/pkg/util" "github.com/zalando-incubator/postgres-operator/pkg/util/constants" "github.com/zalando-incubator/postgres-operator/pkg/util/k8sutil" @@ -318,7 +318,7 @@ func (c *Cluster) applySecrets() error { for secretUsername, secretSpec := range secrets { secret, err := c.KubeClient.Secrets(secretSpec.Namespace).Create(secretSpec) if k8sutil.ResourceAlreadyExists(err) { - var userMap map[string]spec.PgUser + var userMap map[string]types.PgUser curSecret, err := c.KubeClient.Secrets(secretSpec.Namespace).Get(secretSpec.Name) if err != nil { return fmt.Errorf("could not get current secret: %v", err) diff --git a/pkg/cluster/util.go b/pkg/cluster/util.go index b3bfb356..d6f533b7 100644 --- a/pkg/cluster/util.go +++ b/pkg/cluster/util.go @@ -16,6 +16,7 @@ import ( "k8s.io/kubernetes/pkg/client/unversioned/remotecommand" "github.com/zalando-incubator/postgres-operator/pkg/spec" + "github.com/zalando-incubator/postgres-operator/pkg/types" "github.com/zalando-incubator/postgres-operator/pkg/util" "github.com/zalando-incubator/postgres-operator/pkg/util/constants" "github.com/zalando-incubator/postgres-operator/pkg/util/retryutil" @@ -159,7 +160,7 @@ func (c *Cluster) getTeamMembers() ([]string, error) { return teamInfo.Members, nil } -func (c *Cluster) waitForPodLabel(podEvents chan spec.PodEvent) error { +func (c *Cluster) waitForPodLabel(podEvents chan types.PodEvent) error { for { select { case podEvent := <-podEvents: @@ -176,11 +177,11 @@ func (c *Cluster) waitForPodLabel(podEvents chan spec.PodEvent) error { } } -func (c *Cluster) waitForPodDeletion(podEvents chan spec.PodEvent) error { +func (c *Cluster) waitForPodDeletion(podEvents chan types.PodEvent) error { for { select { case podEvent := <-podEvents: - if podEvent.EventType == spec.EventDelete { + if podEvent.EventType == types.EventDelete { return nil } case <-time.After(c.OpConfig.PodDeletionWaitTimeout): @@ -313,7 +314,7 @@ func (c *Cluster) podSpiloRole(pod *v1.Pod) string { return pod.Labels[c.OpConfig.PodRoleLabel] } -func (c *Cluster) ExecCommand(podName *spec.NamespacedName, command ...string) (string, error) { +func (c *Cluster) ExecCommand(podName *types.NamespacedName, command ...string) (string, error) { var ( execOut bytes.Buffer execErr bytes.Buffer diff --git a/pkg/cluster/volumes.go b/pkg/cluster/volumes.go index 7ffc7bb0..8303b235 100644 --- a/pkg/cluster/volumes.go +++ b/pkg/cluster/volumes.go @@ -9,6 +9,7 @@ import ( "k8s.io/client-go/pkg/api/v1" "github.com/zalando-incubator/postgres-operator/pkg/spec" + "github.com/zalando-incubator/postgres-operator/pkg/types" "github.com/zalando-incubator/postgres-operator/pkg/util" "github.com/zalando-incubator/postgres-operator/pkg/util/constants" "github.com/zalando-incubator/postgres-operator/pkg/util/filesystems" @@ -172,11 +173,11 @@ func (c *Cluster) listVolumesWithManifestSize(newVolume spec.Volume) ([]*v1.Pers } // getPodNameFromPersistentVolume returns a pod name that it extracts from the volume claim ref. -func getPodNameFromPersistentVolume(pv *v1.PersistentVolume) *spec.NamespacedName { +func getPodNameFromPersistentVolume(pv *v1.PersistentVolume) *types.NamespacedName { namespace := pv.Spec.ClaimRef.Namespace name := pv.Spec.ClaimRef.Name[len(constants.DataVolumeName)+1:] - return &spec.NamespacedName{namespace, name} + return &types.NamespacedName{namespace, name} } func quantityToGigabyte(q resource.Quantity) int64 { diff --git a/pkg/controller/controller.go b/pkg/controller/controller.go index b3eb242d..f89ccb7a 100644 --- a/pkg/controller/controller.go +++ b/pkg/controller/controller.go @@ -10,8 +10,8 @@ import ( "k8s.io/client-go/rest" "k8s.io/client-go/tools/cache" - "github.com/zalando-incubator/postgres-operator/pkg/cluster" "github.com/zalando-incubator/postgres-operator/pkg/spec" + "github.com/zalando-incubator/postgres-operator/pkg/types" "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" @@ -22,7 +22,7 @@ type Config struct { KubeClient *kubernetes.Clientset RestClient *rest.RESTClient TeamsAPIClient *teams.API - InfrastructureRoles map[string]spec.PgUser + InfrastructureRoles map[string]types.PgUser } type Controller struct { @@ -31,12 +31,12 @@ type Controller struct { logger *logrus.Entry clustersMu sync.RWMutex - clusters map[spec.NamespacedName]cluster.Interface - stopChs map[spec.NamespacedName]chan struct{} + clusters map[types.NamespacedName]types.Cluster + stopChs map[types.NamespacedName]chan struct{} postgresqlInformer cache.SharedIndexInformer podInformer cache.SharedIndexInformer - podCh chan spec.PodEvent + podCh chan types.PodEvent clusterEventQueues []*cache.FIFO @@ -56,9 +56,9 @@ func New(controllerConfig *Config, operatorConfig *config.Config) *Controller { Config: *controllerConfig, opConfig: operatorConfig, logger: logger.WithField("pkg", "controller"), - clusters: make(map[spec.NamespacedName]cluster.Interface), - stopChs: make(map[spec.NamespacedName]chan struct{}), - podCh: make(chan spec.PodEvent), + clusters: make(map[types.NamespacedName]types.Cluster), + stopChs: make(map[types.NamespacedName]chan struct{}), + podCh: make(chan types.PodEvent), } } @@ -130,7 +130,7 @@ func (c *Controller) initController() { c.clusterEventQueues = make([]*cache.FIFO, c.opConfig.Workers) for i := range c.clusterEventQueues { c.clusterEventQueues[i] = cache.NewFIFO(func(obj interface{}) (string, error) { - e, ok := obj.(spec.ClusterEvent) + e, ok := obj.(types.ClusterEvent) if !ok { return "", fmt.Errorf("could not cast to ClusterEvent") } diff --git a/pkg/controller/pod.go b/pkg/controller/pod.go index 3b31d439..5badaae2 100644 --- a/pkg/controller/pod.go +++ b/pkg/controller/pod.go @@ -6,7 +6,7 @@ import ( "k8s.io/client-go/pkg/runtime" "k8s.io/client-go/pkg/watch" - "github.com/zalando-incubator/postgres-operator/pkg/spec" + "github.com/zalando-incubator/postgres-operator/pkg/types" "github.com/zalando-incubator/postgres-operator/pkg/util" ) @@ -61,11 +61,11 @@ func (c *Controller) podAdd(obj interface{}) { return } - podEvent := spec.PodEvent{ + podEvent := types.PodEvent{ ClusterName: c.podClusterName(pod), PodName: util.NameFromMeta(pod.ObjectMeta), CurPod: pod, - EventType: spec.EventAdd, + EventType: types.EventAdd, ResourceVersion: pod.ResourceVersion, } @@ -83,12 +83,12 @@ func (c *Controller) podUpdate(prev, cur interface{}) { return } - podEvent := spec.PodEvent{ + podEvent := types.PodEvent{ ClusterName: c.podClusterName(curPod), PodName: util.NameFromMeta(curPod.ObjectMeta), PrevPod: prevPod, CurPod: curPod, - EventType: spec.EventUpdate, + EventType: types.EventUpdate, ResourceVersion: curPod.ResourceVersion, } @@ -101,11 +101,11 @@ func (c *Controller) podDelete(obj interface{}) { return } - podEvent := spec.PodEvent{ + podEvent := types.PodEvent{ ClusterName: c.podClusterName(pod), PodName: util.NameFromMeta(pod.ObjectMeta), CurPod: pod, - EventType: spec.EventDelete, + EventType: types.EventDelete, ResourceVersion: pod.ResourceVersion, } diff --git a/pkg/controller/postgresql.go b/pkg/controller/postgresql.go index 1f94053a..f2f4f627 100644 --- a/pkg/controller/postgresql.go +++ b/pkg/controller/postgresql.go @@ -10,12 +10,13 @@ import ( "k8s.io/client-go/pkg/api/meta" "k8s.io/client-go/pkg/fields" "k8s.io/client-go/pkg/runtime" - "k8s.io/client-go/pkg/types" + ktypes "k8s.io/client-go/pkg/types" "k8s.io/client-go/pkg/watch" "k8s.io/client-go/tools/cache" "github.com/zalando-incubator/postgres-operator/pkg/cluster" "github.com/zalando-incubator/postgres-operator/pkg/spec" + "github.com/zalando-incubator/postgres-operator/pkg/types" "github.com/zalando-incubator/postgres-operator/pkg/util" "github.com/zalando-incubator/postgres-operator/pkg/util/constants" ) @@ -68,7 +69,7 @@ func (c *Controller) clusterListFunc(options api.ListOptions) (runtime.Object, e failedClustersCnt++ continue } - c.queueClusterEvent(nil, pg, spec.EventSync) + c.queueClusterEvent(nil, pg, types.EventSync) activeClustersCnt++ } if len(objList) > 0 { @@ -97,15 +98,15 @@ func (c *Controller) clusterWatchFunc(options api.ListOptions) (watch.Interface, } func (c *Controller) processEvent(obj interface{}) error { - var clusterName spec.NamespacedName + var clusterName types.NamespacedName - event, ok := obj.(spec.ClusterEvent) + event, ok := obj.(types.ClusterEvent) if !ok { return fmt.Errorf("could not cast to ClusterEvent") } logger := c.logger.WithField("worker", event.WorkerID) - if event.EventType == spec.EventAdd || event.EventType == spec.EventSync { + if event.EventType == types.EventAdd || event.EventType == types.EventSync { clusterName = util.NameFromMeta(event.NewSpec.Metadata) } else { clusterName = util.NameFromMeta(event.OldSpec.Metadata) @@ -116,7 +117,7 @@ func (c *Controller) processEvent(obj interface{}) error { c.clustersMu.RUnlock() switch event.EventType { - case spec.EventAdd: + case types.EventAdd: if clusterFound { logger.Debugf("Cluster '%s' already exists", clusterName) return nil @@ -142,7 +143,7 @@ func (c *Controller) processEvent(obj interface{}) error { } logger.Infof("Cluster '%s' has been created", clusterName) - case spec.EventUpdate: + case types.EventUpdate: logger.Infof("Update of the '%s' cluster started", clusterName) if !clusterFound { @@ -158,7 +159,7 @@ func (c *Controller) processEvent(obj interface{}) error { } cl.SetFailed(nil) logger.Infof("Cluster '%s' has been updated", clusterName) - case spec.EventDelete: + case types.EventDelete: logger.Infof("Deletion of the '%s' cluster started", clusterName) if !clusterFound { logger.Errorf("Unknown cluster: %s", clusterName) @@ -177,7 +178,7 @@ func (c *Controller) processEvent(obj interface{}) error { c.clustersMu.Unlock() logger.Infof("Cluster '%s' has been deleted", clusterName) - case spec.EventSync: + case types.EventSync: logger.Infof("Syncing of the '%s' cluster started", clusterName) // no race condition because a cluster is always processed by single worker @@ -214,18 +215,18 @@ func (c *Controller) processClusterEventsQueue(idx int) { } } -func (c *Controller) queueClusterEvent(old, new *spec.Postgresql, eventType spec.EventType) { +func (c *Controller) queueClusterEvent(old, new *spec.Postgresql, eventType types.EventType) { var ( - uid types.UID - clusterName spec.NamespacedName + uid ktypes.UID + clusterName types.NamespacedName clusterError error ) if old != nil { //update, delete uid = old.Metadata.GetUID() clusterName = util.NameFromMeta(old.Metadata) - if eventType == spec.EventUpdate && new.Error == nil && old.Error != nil { - eventType = spec.EventSync + if eventType == types.EventUpdate && new.Error == nil && old.Error != nil { + eventType = types.EventSync clusterError = new.Error } else { clusterError = old.Error @@ -236,13 +237,13 @@ func (c *Controller) queueClusterEvent(old, new *spec.Postgresql, eventType spec clusterError = new.Error } - if clusterError != nil && eventType != spec.EventDelete { + if clusterError != nil && eventType != types.EventDelete { c.logger.Debugf("Skipping %s event for invalid cluster %s (reason: %v)", eventType, clusterName, clusterError) return } workerID := c.clusterWorkerID(clusterName) - clusterEvent := spec.ClusterEvent{ + clusterEvent := types.ClusterEvent{ EventType: eventType, UID: uid, OldSpec: old, @@ -265,7 +266,7 @@ func (c *Controller) postgresqlAdd(obj interface{}) { } // We will not get multiple Add events for the same cluster - c.queueClusterEvent(nil, pg, spec.EventAdd) + c.queueClusterEvent(nil, pg, types.EventAdd) } func (c *Controller) postgresqlUpdate(prev, cur interface{}) { @@ -284,7 +285,7 @@ func (c *Controller) postgresqlUpdate(prev, cur interface{}) { return } - c.queueClusterEvent(pgOld, pgNew, spec.EventUpdate) + c.queueClusterEvent(pgOld, pgNew, types.EventUpdate) } func (c *Controller) postgresqlDelete(obj interface{}) { @@ -294,5 +295,5 @@ func (c *Controller) postgresqlDelete(obj interface{}) { return } - c.queueClusterEvent(pg, nil, spec.EventDelete) + c.queueClusterEvent(pg, nil, types.EventDelete) } diff --git a/pkg/controller/util.go b/pkg/controller/util.go index 76b33168..74a7e497 100644 --- a/pkg/controller/util.go +++ b/pkg/controller/util.go @@ -8,14 +8,14 @@ import ( extv1beta "k8s.io/client-go/pkg/apis/extensions/v1beta1" "github.com/zalando-incubator/postgres-operator/pkg/cluster" - "github.com/zalando-incubator/postgres-operator/pkg/spec" + "github.com/zalando-incubator/postgres-operator/pkg/types" "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" ) func (c *Controller) makeClusterConfig() cluster.Config { - infrastructureRoles := make(map[string]spec.PgUser) + infrastructureRoles := make(map[string]types.PgUser) for k, v := range c.InfrastructureRoles { infrastructureRoles[k] = v } @@ -43,7 +43,7 @@ func thirdPartyResource(TPRName string) *extv1beta.ThirdPartyResource { } } -func (c *Controller) clusterWorkerID(clusterName spec.NamespacedName) uint32 { +func (c *Controller) clusterWorkerID(clusterName types.NamespacedName) uint32 { return crc32.ChecksumIEEE([]byte(clusterName.String())) % c.opConfig.Workers } @@ -64,8 +64,8 @@ func (c *Controller) createTPR() error { return k8sutil.WaitTPRReady(c.RestClient, c.opConfig.TPR.ReadyWaitInterval, c.opConfig.TPR.ReadyWaitTimeout, c.opConfig.Namespace) } -func (c *Controller) getInfrastructureRoles() (result map[string]spec.PgUser, err error) { - if c.opConfig.InfrastructureRolesSecretName == (spec.NamespacedName{}) { +func (c *Controller) getInfrastructureRoles() (result map[string]types.PgUser, err error) { + if c.opConfig.InfrastructureRolesSecretName == (types.NamespacedName{}) { // we don't have infrastructure roles defined, bail out return nil, nil } @@ -79,12 +79,12 @@ func (c *Controller) getInfrastructureRoles() (result map[string]spec.PgUser, er } data := infraRolesSecret.Data - result = make(map[string]spec.PgUser) + result = make(map[string]types.PgUser) Users: // in worst case we would have one line per user for i := 1; i <= len(data); i++ { properties := []string{"user", "password", "inrole"} - t := spec.PgUser{} + t := types.PgUser{} for _, p := range properties { key := fmt.Sprintf("%s%d", p, i) if val, present := data[key]; !present { @@ -115,13 +115,13 @@ Users: return result, nil } -func (c *Controller) podClusterName(pod *v1.Pod) spec.NamespacedName { +func (c *Controller) podClusterName(pod *v1.Pod) types.NamespacedName { if name, ok := pod.Labels[c.opConfig.ClusterNameLabel]; ok { - return spec.NamespacedName{ + return types.NamespacedName{ Namespace: pod.Namespace, Name: name, } } - return spec.NamespacedName{} + return types.NamespacedName{} } diff --git a/pkg/types/namespacedname.go b/pkg/types/namespacedname.go new file mode 100644 index 00000000..6d220274 --- /dev/null +++ b/pkg/types/namespacedname.go @@ -0,0 +1,41 @@ +package types + +import ( + "fmt" + "strings" + + "k8s.io/client-go/pkg/api/v1" + "k8s.io/client-go/pkg/types" +) + +// NamespacedName describes the namespace/name pairs used in Kubernetes names. +type NamespacedName types.NamespacedName + +func (n NamespacedName) String() string { + return types.NamespacedName(n).String() +} + +// MarshalJSON defines marshaling rule for the namespaced name type. +func (n NamespacedName) MarshalJSON() ([]byte, error) { + return []byte("\"" + n.String() + "\""), nil +} + +// Decode converts a (possibly unqualified) string into the namespaced name object. +func (n *NamespacedName) Decode(value string) error { + name := types.NewNamespacedNameFromString(value) + + if strings.Trim(value, string(types.Separator)) != "" && name == (types.NamespacedName{}) { + name.Name = value + name.Namespace = v1.NamespaceDefault + } else if name.Namespace == "" { + name.Namespace = v1.NamespaceDefault + } + + if name.Name == "" { + return fmt.Errorf("Incorrect namespaced name") + } + + *n = NamespacedName(name) + + return nil +} diff --git a/pkg/spec/types.go b/pkg/types/types.go similarity index 61% rename from pkg/spec/types.go rename to pkg/types/types.go index 9d189d90..bd314cd0 100644 --- a/pkg/spec/types.go +++ b/pkg/types/types.go @@ -1,20 +1,17 @@ -package spec +package types import ( "database/sql" - "fmt" - "strings" "k8s.io/client-go/pkg/api/v1" "k8s.io/client-go/pkg/types" + + "github.com/zalando-incubator/postgres-operator/pkg/spec" ) // EvenType contains type of the events for the TPRs and Pods received from Kubernetes type EventType string -// NamespacedName describes the namespace/name pairs used in Kubernetes names. -type NamespacedName types.NamespacedName - // Possible values for the EventType const ( EventAdd EventType = "ADD" @@ -27,8 +24,8 @@ const ( type ClusterEvent struct { UID types.UID EventType EventType - OldSpec *Postgresql - NewSpec *Postgresql + OldSpec *spec.Postgresql + NewSpec *spec.Postgresql WorkerID uint32 } @@ -73,31 +70,13 @@ type UserSyncer interface { ExecuteSyncRequests(req []PgSyncUserRequest, db *sql.DB) error } -func (n NamespacedName) String() string { - return types.NamespacedName(n).String() -} - -// MarshalJSON defines marshaling rule for the namespaced name type. -func (n NamespacedName) MarshalJSON() ([]byte, error) { - return []byte("\"" + n.String() + "\""), nil -} - -// Decode converts a (possibly unqualified) string into the namespaced name object. -func (n *NamespacedName) Decode(value string) error { - name := types.NewNamespacedNameFromString(value) - - if strings.Trim(value, string(types.Separator)) != "" && name == (types.NamespacedName{}) { - name.Name = value - name.Namespace = v1.NamespaceDefault - } else if name.Namespace == "" { - name.Namespace = v1.NamespaceDefault - } - - if name.Name == "" { - return fmt.Errorf("Incorrect namespaced name") - } - - *n = NamespacedName(name) - - return nil +type Cluster interface { + Create() error + Delete() error + ExecCommand(podName *NamespacedName, command ...string) (string, error) + ReceivePodEvent(event PodEvent) + Run(stopCh <-chan struct{}) + Sync() error + Update(newSpec *spec.Postgresql) error + SetFailed(err error) } diff --git a/pkg/spec/types_test.go b/pkg/types/types_test.go similarity index 98% rename from pkg/spec/types_test.go rename to pkg/types/types_test.go index b690586e..288e3088 100644 --- a/pkg/spec/types_test.go +++ b/pkg/types/types_test.go @@ -1,4 +1,4 @@ -package spec +package types import ( "bytes" diff --git a/pkg/util/config/config.go b/pkg/util/config/config.go index 7676e3e6..52c5f650 100644 --- a/pkg/util/config/config.go +++ b/pkg/util/config/config.go @@ -5,7 +5,7 @@ import ( "strings" "time" - "github.com/zalando-incubator/postgres-operator/pkg/spec" + "github.com/zalando-incubator/postgres-operator/pkg/types" ) type TPR struct { @@ -29,13 +29,13 @@ type Resources struct { } type Auth struct { - PamRoleName string `name:"pam_rol_name" default:"zalandos"` - PamConfiguration string `name:"pam_configuration" default:"https://info.example.com/oauth2/tokeninfo?access_token= uid realm=/employees"` - TeamsAPIUrl string `name:"teams_api_url" default:"https://teams.example.com/api/"` - OAuthTokenSecretName spec.NamespacedName `name:"oauth_token_secret_name" default:"postgresql-operator"` - InfrastructureRolesSecretName spec.NamespacedName `name:"infrastructure_roles_secret_name"` - SuperUsername string `name:"super_username" default:"postgres"` - ReplicationUsername string `name:"replication_username" default:"replication"` + PamRoleName string `name:"pam_rol_name" default:"zalandos"` + PamConfiguration string `name:"pam_configuration" default:"https://info.example.com/oauth2/tokeninfo?access_token= uid realm=/employees"` + TeamsAPIUrl string `name:"teams_api_url" default:"https://teams.example.com/api/"` + OAuthTokenSecretName types.NamespacedName `name:"oauth_token_secret_name" default:"postgresql-operator"` + InfrastructureRolesSecretName types.NamespacedName `name:"infrastructure_roles_secret_name"` + SuperUsername string `name:"super_username" default:"postgres"` + ReplicationUsername string `name:"replication_username" default:"replication"` } type Config struct { diff --git a/pkg/util/users/users.go b/pkg/util/users/users.go index 8ff32d30..b59707b2 100644 --- a/pkg/util/users/users.go +++ b/pkg/util/users/users.go @@ -5,7 +5,7 @@ import ( "fmt" "strings" - "github.com/zalando-incubator/postgres-operator/pkg/spec" + "github.com/zalando-incubator/postgres-operator/pkg/types" "github.com/zalando-incubator/postgres-operator/pkg/util" ) @@ -26,31 +26,31 @@ type DefaultUserSyncStrategy struct { } // ProduceSyncRequests figures out the types of changes that need to happen with the given users. -func (s DefaultUserSyncStrategy) ProduceSyncRequests(dbUsers spec.PgUserMap, - newUsers spec.PgUserMap) (reqs []spec.PgSyncUserRequest) { +func (s DefaultUserSyncStrategy) ProduceSyncRequests(dbUsers types.PgUserMap, + newUsers types.PgUserMap) (reqs []types.PgSyncUserRequest) { // No existing roles are deleted or stripped of role memebership/flags for name, newUser := range newUsers { dbUser, exists := dbUsers[name] if !exists { - reqs = append(reqs, spec.PgSyncUserRequest{Kind: spec.PGSyncUserAdd, User: newUser}) + reqs = append(reqs, types.PgSyncUserRequest{Kind: types.PGSyncUserAdd, User: newUser}) } else { - r := spec.PgSyncUserRequest{} + r := types.PgSyncUserRequest{} newMD5Password := util.PGUserPassword(newUser) if dbUser.Password != newMD5Password { r.User.Password = newMD5Password - r.Kind = spec.PGsyncUserAlter + r.Kind = types.PGsyncUserAlter } if addNewRoles, equal := util.SubstractStringSlices(newUser.MemberOf, dbUser.MemberOf); !equal { r.User.MemberOf = addNewRoles - r.Kind = spec.PGsyncUserAlter + r.Kind = types.PGsyncUserAlter } if addNewFlags, equal := util.SubstractStringSlices(newUser.Flags, dbUser.Flags); !equal { r.User.Flags = addNewFlags - r.Kind = spec.PGsyncUserAlter + r.Kind = types.PGsyncUserAlter } - if r.Kind == spec.PGsyncUserAlter { + if r.Kind == types.PGsyncUserAlter { r.User.Name = newUser.Name reqs = append(reqs, r) } @@ -61,14 +61,14 @@ func (s DefaultUserSyncStrategy) ProduceSyncRequests(dbUsers spec.PgUserMap, } // ExecuteSyncRequests makes actual database changes from the requests passed in its arguments. -func (s DefaultUserSyncStrategy) ExecuteSyncRequests(reqs []spec.PgSyncUserRequest, db *sql.DB) error { +func (s DefaultUserSyncStrategy) ExecuteSyncRequests(reqs []types.PgSyncUserRequest, db *sql.DB) error { for _, r := range reqs { switch r.Kind { - case spec.PGSyncUserAdd: + case types.PGSyncUserAdd: if err := s.createPgUser(r.User, db); err != nil { return fmt.Errorf("could not create user '%s': %v", r.User.Name, err) } - case spec.PGsyncUserAlter: + case types.PGsyncUserAlter: if err := s.alterPgUser(r.User, db); err != nil { return fmt.Errorf("could not alter user '%s': %v", r.User.Name, err) } @@ -80,7 +80,7 @@ func (s DefaultUserSyncStrategy) ExecuteSyncRequests(reqs []spec.PgSyncUserReque return nil } -func (s DefaultUserSyncStrategy) createPgUser(user spec.PgUser, db *sql.DB) (err error) { +func (s DefaultUserSyncStrategy) createPgUser(user types.PgUser, db *sql.DB) (err error) { var userFlags []string var userPassword string @@ -107,7 +107,7 @@ func (s DefaultUserSyncStrategy) createPgUser(user spec.PgUser, db *sql.DB) (err return } -func (s DefaultUserSyncStrategy) alterPgUser(user spec.PgUser, db *sql.DB) (err error) { +func (s DefaultUserSyncStrategy) alterPgUser(user types.PgUser, db *sql.DB) (err error) { var resultStmt []string if user.Password != "" || len(user.Flags) > 0 { @@ -129,7 +129,7 @@ func (s DefaultUserSyncStrategy) alterPgUser(user spec.PgUser, db *sql.DB) (err return } -func produceAlterStmt(user spec.PgUser) string { +func produceAlterStmt(user types.PgUser) string { // ALTER ROLE ... LOGIN ENCRYPTED PASSWORD .. result := make([]string, 1) password := user.Password @@ -144,12 +144,12 @@ func produceAlterStmt(user spec.PgUser) string { return fmt.Sprintf(alterUserSQL, user.Name, strings.Join(result, " ")) } -func produceGrantStmt(user spec.PgUser) string { +func produceGrantStmt(user types.PgUser) string { // GRANT ROLE "foo", "bar" TO baz return fmt.Sprintf(grantToUserSQL, quoteMemberList(user), user.Name) } -func quoteMemberList(user spec.PgUser) string { +func quoteMemberList(user types.PgUser) string { var memberof []string for _, member := range user.MemberOf { memberof = append(memberof, fmt.Sprintf(`"%s"`, member)) diff --git a/pkg/util/util.go b/pkg/util/util.go index abe4a823..7be14077 100644 --- a/pkg/util/util.go +++ b/pkg/util/util.go @@ -10,7 +10,7 @@ import ( "github.com/motomux/pretty" "k8s.io/client-go/pkg/api/v1" - "github.com/zalando-incubator/postgres-operator/pkg/spec" + "github.com/zalando-incubator/postgres-operator/pkg/types" ) const ( @@ -34,15 +34,15 @@ func RandomPassword(n int) string { } // NameFromMeta converts a metadata object to the NamespacedName name representation. -func NameFromMeta(meta v1.ObjectMeta) spec.NamespacedName { - return spec.NamespacedName{ +func NameFromMeta(meta v1.ObjectMeta) types.NamespacedName { + return types.NamespacedName{ Namespace: meta.Namespace, Name: meta.Name, } } // PGUserPassword is used to generate md5 password hash for a given user. It does nothing for already hashed passwords. -func PGUserPassword(user spec.PgUser) string { +func PGUserPassword(user types.PgUser) string { if (len(user.Password) == md5.Size*2+len(md5prefix) && user.Password[:3] == md5prefix) || user.Password == "" { // Avoid processing already encrypted or empty passwords return user.Password diff --git a/pkg/util/util_test.go b/pkg/util/util_test.go index 067f6492..e93c0f54 100644 --- a/pkg/util/util_test.go +++ b/pkg/util/util_test.go @@ -10,15 +10,15 @@ import ( ) var pgUsers = []struct { - in spec.PgUser + in types.PgUser out string -}{{spec.PgUser{ +}{{types.PgUser{ Name: "test", Password: "password", Flags: []string{}, MemberOf: []string{}}, "md587f77988ccb5aa917c93201ba314fcd4"}, - {spec.PgUser{ + {types.PgUser{ Name: "test", Password: "md592f413f3974bdf3799bb6fecb5f9f2c6", Flags: []string{}, @@ -58,7 +58,7 @@ func TestNameFromMeta(t *testing.T) { Namespace: "default", } - expected := spec.NamespacedName{ + expected := types.NamespacedName{ Name: "testcluster", Namespace: "default", } -- GitLab