Add a simple tests for CreateSecret
This commit is contained in:
parent
ba1f886043
commit
b0756a1f75
|
|
@ -127,6 +127,14 @@ func New(cfg Config, kubeClient k8sutil.KubernetesClient, pgSpec acidv1.Postgres
|
||||||
return cluster
|
return cluster
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Cluster) SetTeamsAPIClient(client teams.Interface) {
|
||||||
|
c.teamsAPIClient = client
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Cluster) SetOAuthTokenGetter(getter OAuthTokenGetter) {
|
||||||
|
c.oauthTokenGetter = getter
|
||||||
|
}
|
||||||
|
|
||||||
func (c *Cluster) clusterName() spec.NamespacedName {
|
func (c *Cluster) clusterName() spec.NamespacedName {
|
||||||
return util.NameFromMeta(c.ObjectMeta)
|
return util.NameFromMeta(c.ObjectMeta)
|
||||||
}
|
}
|
||||||
|
|
@ -222,7 +230,7 @@ func (c *Cluster) PlanForSecrets() (plan Plan) {
|
||||||
|
|
||||||
if k8sutil.ResourceNotFound(err) {
|
if k8sutil.ResourceNotFound(err) {
|
||||||
msg = "Generate plan to create new secret %q"
|
msg = "Generate plan to create new secret %q"
|
||||||
c.logger.Debugf(msg, util.NameFromMeta(secret.ObjectMeta))
|
c.logger.Debugf(msg, util.NameFromMeta(secretSpec.ObjectMeta))
|
||||||
plan = append(plan, NewCreateSecret(secretUsername, secretSpec, c))
|
plan = append(plan, NewCreateSecret(secretUsername, secretSpec, c))
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ import (
|
||||||
"k8s.io/client-go/kubernetes/scheme"
|
"k8s.io/client-go/kubernetes/scheme"
|
||||||
"k8s.io/client-go/tools/cache"
|
"k8s.io/client-go/tools/cache"
|
||||||
|
|
||||||
|
acidv1 "github.com/zalando-incubator/postgres-operator/pkg/apis/acid.zalan.do/v1"
|
||||||
"github.com/zalando-incubator/postgres-operator/pkg/apiserver"
|
"github.com/zalando-incubator/postgres-operator/pkg/apiserver"
|
||||||
"github.com/zalando-incubator/postgres-operator/pkg/cluster"
|
"github.com/zalando-incubator/postgres-operator/pkg/cluster"
|
||||||
"github.com/zalando-incubator/postgres-operator/pkg/spec"
|
"github.com/zalando-incubator/postgres-operator/pkg/spec"
|
||||||
|
|
@ -25,6 +26,20 @@ import (
|
||||||
acidv1informer "github.com/zalando-incubator/postgres-operator/pkg/generated/informers/externalversions/acid.zalan.do/v1"
|
acidv1informer "github.com/zalando-incubator/postgres-operator/pkg/generated/informers/externalversions/acid.zalan.do/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type ClusterFactory interface {
|
||||||
|
addCluster(ctrl *Controller,
|
||||||
|
lg *logrus.Entry,
|
||||||
|
clusterName spec.NamespacedName,
|
||||||
|
pgSpec *acidv1.Postgresql,
|
||||||
|
) *cluster.Cluster
|
||||||
|
}
|
||||||
|
|
||||||
|
type ClusterGenerator struct {
|
||||||
|
ClusterFactory
|
||||||
|
|
||||||
|
KubeClient k8sutil.KubernetesClient
|
||||||
|
}
|
||||||
|
|
||||||
// Controller represents operator controller
|
// Controller represents operator controller
|
||||||
type Controller struct {
|
type Controller struct {
|
||||||
config spec.ControllerConfig
|
config spec.ControllerConfig
|
||||||
|
|
@ -59,6 +74,8 @@ type Controller struct {
|
||||||
PodServiceAccount *v1.ServiceAccount
|
PodServiceAccount *v1.ServiceAccount
|
||||||
PodServiceAccountRoleBinding *rbacv1beta1.RoleBinding
|
PodServiceAccountRoleBinding *rbacv1beta1.RoleBinding
|
||||||
namespacesWithDefinedRBAC sync.Map
|
namespacesWithDefinedRBAC sync.Map
|
||||||
|
|
||||||
|
clusterFactory ClusterFactory
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewController creates a new controller
|
// NewController creates a new controller
|
||||||
|
|
@ -77,6 +94,7 @@ func NewController(controllerConfig *spec.ControllerConfig) *Controller {
|
||||||
teamClusters: make(map[string][]spec.NamespacedName),
|
teamClusters: make(map[string][]spec.NamespacedName),
|
||||||
stopCh: make(chan struct{}),
|
stopCh: make(chan struct{}),
|
||||||
podCh: make(chan cluster.PodEvent),
|
podCh: make(chan cluster.PodEvent),
|
||||||
|
clusterFactory: &ClusterGenerator{},
|
||||||
}
|
}
|
||||||
logger.Hooks.Add(c)
|
logger.Hooks.Add(c)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -136,7 +136,7 @@ func (c *Controller) acquireInitialListOfClusters() error {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
clusterName = util.NameFromMeta(pg.ObjectMeta)
|
clusterName = util.NameFromMeta(pg.ObjectMeta)
|
||||||
c.addCluster(c.logger, clusterName, &pg)
|
c.clusterFactory.addCluster(c, c.logger, clusterName, &pg)
|
||||||
c.logger.Debugf("added new cluster: %q", clusterName)
|
c.logger.Debugf("added new cluster: %q", clusterName)
|
||||||
}
|
}
|
||||||
// initiate initial sync of all clusters.
|
// initiate initial sync of all clusters.
|
||||||
|
|
@ -144,18 +144,20 @@ func (c *Controller) acquireInitialListOfClusters() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Controller) addCluster(lg *logrus.Entry, clusterName spec.NamespacedName, pgSpec *acidv1.Postgresql) *cluster.Cluster {
|
func (c *ClusterGenerator) addCluster(ctrl *Controller,
|
||||||
cl := cluster.New(c.makeClusterConfig(), c.KubeClient, *pgSpec, lg)
|
lg *logrus.Entry, clusterName spec.NamespacedName, pgSpec *acidv1.Postgresql) *cluster.Cluster {
|
||||||
cl.Run(c.stopCh)
|
|
||||||
|
cl := cluster.New(ctrl.makeClusterConfig(), ctrl.KubeClient, *pgSpec, lg)
|
||||||
|
cl.Run(ctrl.stopCh)
|
||||||
teamName := strings.ToLower(cl.Spec.TeamID)
|
teamName := strings.ToLower(cl.Spec.TeamID)
|
||||||
|
|
||||||
defer c.clustersMu.Unlock()
|
defer ctrl.clustersMu.Unlock()
|
||||||
c.clustersMu.Lock()
|
ctrl.clustersMu.Lock()
|
||||||
|
|
||||||
c.teamClusters[teamName] = append(c.teamClusters[teamName], clusterName)
|
ctrl.teamClusters[teamName] = append(ctrl.teamClusters[teamName], clusterName)
|
||||||
c.clusters[clusterName] = cl
|
ctrl.clusters[clusterName] = cl
|
||||||
c.clusterLogs[clusterName] = ringlog.New(c.opConfig.RingLogLines)
|
ctrl.clusterLogs[clusterName] = ringlog.New(ctrl.opConfig.RingLogLines)
|
||||||
c.clusterHistory[clusterName] = ringlog.New(c.opConfig.ClusterHistoryEntries)
|
ctrl.clusterHistory[clusterName] = ringlog.New(ctrl.opConfig.ClusterHistoryEntries)
|
||||||
|
|
||||||
return cl
|
return cl
|
||||||
}
|
}
|
||||||
|
|
@ -182,7 +184,7 @@ func (c *Controller) generatePlan(event ClusterEvent) cluster.Plan {
|
||||||
case EventAdd:
|
case EventAdd:
|
||||||
log.Infof("Creation of the cluster started")
|
log.Infof("Creation of the cluster started")
|
||||||
|
|
||||||
newCluster := c.addCluster(log, clusterName, event.NewSpec)
|
newCluster := c.clusterFactory.addCluster(c, log, clusterName, event.NewSpec)
|
||||||
c.curWorkerCluster.Store(event.WorkerID, newCluster)
|
c.curWorkerCluster.Store(event.WorkerID, newCluster)
|
||||||
return newCluster.PlanForCreate()
|
return newCluster.PlanForCreate()
|
||||||
|
|
||||||
|
|
@ -272,7 +274,7 @@ func (c *Controller) processEvent(event ClusterEvent) {
|
||||||
|
|
||||||
lg.Infof("creation of the cluster started")
|
lg.Infof("creation of the cluster started")
|
||||||
|
|
||||||
cl = c.addCluster(lg, clusterName, event.NewSpec)
|
cl = c.clusterFactory.addCluster(c, lg, clusterName, event.NewSpec)
|
||||||
|
|
||||||
c.curWorkerCluster.Store(event.WorkerID, cl)
|
c.curWorkerCluster.Store(event.WorkerID, cl)
|
||||||
|
|
||||||
|
|
@ -341,7 +343,7 @@ func (c *Controller) processEvent(event ClusterEvent) {
|
||||||
|
|
||||||
// no race condition because a cluster is always processed by single worker
|
// no race condition because a cluster is always processed by single worker
|
||||||
if !clusterFound {
|
if !clusterFound {
|
||||||
cl = c.addCluster(lg, clusterName, event.NewSpec)
|
cl = c.clusterFactory.addCluster(c, lg, clusterName, event.NewSpec)
|
||||||
}
|
}
|
||||||
|
|
||||||
c.curWorkerCluster.Store(event.WorkerID, cl)
|
c.curWorkerCluster.Store(event.WorkerID, cl)
|
||||||
|
|
|
||||||
|
|
@ -1,20 +1,101 @@
|
||||||
package controller
|
package controller
|
||||||
|
|
||||||
import (
|
import (
|
||||||
acidv1 "github.com/zalando-incubator/postgres-operator/pkg/apis/acid.zalan.do/v1"
|
|
||||||
"github.com/zalando-incubator/postgres-operator/pkg/spec"
|
|
||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/Sirupsen/logrus"
|
||||||
|
"k8s.io/api/core/v1"
|
||||||
|
|
||||||
|
acidv1 "github.com/zalando-incubator/postgres-operator/pkg/apis/acid.zalan.do/v1"
|
||||||
|
"github.com/zalando-incubator/postgres-operator/pkg/cluster"
|
||||||
|
"github.com/zalando-incubator/postgres-operator/pkg/spec"
|
||||||
|
"github.com/zalando-incubator/postgres-operator/pkg/util/k8sutil"
|
||||||
|
"github.com/zalando-incubator/postgres-operator/pkg/util/teams"
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
v1core "k8s.io/client-go/kubernetes/typed/core/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
True = true
|
True = true
|
||||||
False = false
|
False = false
|
||||||
|
logger = logrus.New().WithField("test", "cluster")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
superUserName = "postgres"
|
||||||
|
replicationUserName = "standby"
|
||||||
|
)
|
||||||
|
|
||||||
|
var mockTeamsAPI mockTeamsAPIClient
|
||||||
|
|
||||||
|
type mockOAuthTokenGetter struct {
|
||||||
|
cluster.OAuthTokenGetter
|
||||||
|
}
|
||||||
|
|
||||||
|
type mockClusterGenerator struct {
|
||||||
|
ClusterGenerator
|
||||||
|
}
|
||||||
|
|
||||||
|
type NotFoundError struct{}
|
||||||
|
|
||||||
|
func (e *NotFoundError) Error() string {
|
||||||
|
return "error"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *NotFoundError) Status() metav1.Status {
|
||||||
|
return metav1.Status{
|
||||||
|
Reason: metav1.StatusReasonNotFound,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *mockClusterGenerator) addCluster(ctrl *Controller,
|
||||||
|
lg *logrus.Entry, clusterName spec.NamespacedName, pgSpec *acidv1.Postgresql) *cluster.Cluster {
|
||||||
|
|
||||||
|
mockTeamsAPI.setMembers([]string{"test-user"})
|
||||||
|
cl := cluster.New(ctrl.makeClusterConfig(), ctrl.KubeClient, *pgSpec, lg)
|
||||||
|
cl.SetTeamsAPIClient(&mockTeamsAPI)
|
||||||
|
cl.SetOAuthTokenGetter(&mockOAuthTokenGetter{})
|
||||||
|
cl.Spec.TeamID = "test-team"
|
||||||
|
return cl
|
||||||
|
}
|
||||||
|
|
||||||
|
type mockTeamsAPIClient struct {
|
||||||
|
members []string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *mockTeamsAPIClient) TeamInfo(teamID, token string) (tm *teams.Team, err error) {
|
||||||
|
return &teams.Team{Members: m.members}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *mockTeamsAPIClient) setMembers(members []string) {
|
||||||
|
m.members = members
|
||||||
|
}
|
||||||
|
|
||||||
|
type mockNoSecretGetter struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
type testNoSecret struct {
|
||||||
|
v1core.SecretInterface
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *testNoSecret) Get(name string, options metav1.GetOptions) (*v1.Secret, error) {
|
||||||
|
return nil, &NotFoundError{}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *mockNoSecretGetter) Secrets(namespace string) v1core.SecretInterface {
|
||||||
|
return &testNoSecret{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func mockKubernetesClient() k8sutil.KubernetesClient {
|
||||||
|
return k8sutil.KubernetesClient{
|
||||||
|
SecretsGetter: &mockNoSecretGetter{},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestMergeDeprecatedPostgreSQLSpecParameters(t *testing.T) {
|
func TestMergeDeprecatedPostgreSQLSpecParameters(t *testing.T) {
|
||||||
c := NewController(&spec.ControllerConfig{})
|
c := NewController(&spec.ControllerConfig{})
|
||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
in *acidv1.PostgresSpec
|
in *acidv1.PostgresSpec
|
||||||
|
|
@ -42,3 +123,43 @@ func TestMergeDeprecatedPostgreSQLSpecParameters(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestGeneratePlan(t *testing.T) {
|
||||||
|
c := NewController(&spec.ControllerConfig{})
|
||||||
|
c.opConfig.SuperUsername = "test-superuser"
|
||||||
|
c.opConfig.SecretNameTemplate = "secret"
|
||||||
|
c.clusterFactory = &mockClusterGenerator{}
|
||||||
|
c.KubeClient = mockKubernetesClient()
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
in ClusterEvent
|
||||||
|
contains cluster.Plan
|
||||||
|
error string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"Cluster add produces plan with a CreateSecret",
|
||||||
|
ClusterEvent{
|
||||||
|
EventType: EventAdd,
|
||||||
|
NewSpec: &acidv1.Postgresql{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "TestCluster",
|
||||||
|
Namespace: "TestNamespace",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
[]cluster.Action{cluster.CreateSecret{}, cluster.CreateSecret{}},
|
||||||
|
"A plan for a new cluster should create secrets",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
result := c.generatePlan(tt.in)
|
||||||
|
for idx, output := range result {
|
||||||
|
output := reflect.TypeOf(output)
|
||||||
|
expected := reflect.TypeOf(tt.contains[idx])
|
||||||
|
if output != expected {
|
||||||
|
t.Errorf("%s: %v", tt.name, tt.error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -196,10 +196,10 @@ func (c *Controller) podClusterName(pod *v1.Pod) spec.NamespacedName {
|
||||||
}
|
}
|
||||||
|
|
||||||
func eventInSlice(a EventType, list []EventType) bool {
|
func eventInSlice(a EventType, list []EventType) bool {
|
||||||
for _, b := range list {
|
for _, b := range list {
|
||||||
if b == a {
|
if b == a {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue