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 | ||||
| } | ||||
| 
 | ||||
| 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 { | ||||
| 	return util.NameFromMeta(c.ObjectMeta) | ||||
| } | ||||
|  | @ -222,7 +230,7 @@ func (c *Cluster) PlanForSecrets() (plan Plan) { | |||
| 
 | ||||
| 		if k8sutil.ResourceNotFound(err) { | ||||
| 			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)) | ||||
| 			continue | ||||
| 		} | ||||
|  |  | |||
|  | @ -13,6 +13,7 @@ import ( | |||
| 	"k8s.io/client-go/kubernetes/scheme" | ||||
| 	"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/cluster" | ||||
| 	"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" | ||||
| ) | ||||
| 
 | ||||
| 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
 | ||||
| type Controller struct { | ||||
| 	config   spec.ControllerConfig | ||||
|  | @ -59,6 +74,8 @@ type Controller struct { | |||
| 	PodServiceAccount            *v1.ServiceAccount | ||||
| 	PodServiceAccountRoleBinding *rbacv1beta1.RoleBinding | ||||
| 	namespacesWithDefinedRBAC    sync.Map | ||||
| 
 | ||||
| 	clusterFactory ClusterFactory | ||||
| } | ||||
| 
 | ||||
| // NewController creates a new controller
 | ||||
|  | @ -77,6 +94,7 @@ func NewController(controllerConfig *spec.ControllerConfig) *Controller { | |||
| 		teamClusters:     make(map[string][]spec.NamespacedName), | ||||
| 		stopCh:           make(chan struct{}), | ||||
| 		podCh:            make(chan cluster.PodEvent), | ||||
| 		clusterFactory:   &ClusterGenerator{}, | ||||
| 	} | ||||
| 	logger.Hooks.Add(c) | ||||
| 
 | ||||
|  |  | |||
|  | @ -136,7 +136,7 @@ func (c *Controller) acquireInitialListOfClusters() error { | |||
| 			continue | ||||
| 		} | ||||
| 		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) | ||||
| 	} | ||||
| 	// initiate initial sync of all clusters.
 | ||||
|  | @ -144,18 +144,20 @@ func (c *Controller) acquireInitialListOfClusters() error { | |||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func (c *Controller) addCluster(lg *logrus.Entry, clusterName spec.NamespacedName, pgSpec *acidv1.Postgresql) *cluster.Cluster { | ||||
| 	cl := cluster.New(c.makeClusterConfig(), c.KubeClient, *pgSpec, lg) | ||||
| 	cl.Run(c.stopCh) | ||||
| func (c *ClusterGenerator) addCluster(ctrl *Controller, | ||||
| 	lg *logrus.Entry, clusterName spec.NamespacedName, pgSpec *acidv1.Postgresql) *cluster.Cluster { | ||||
| 
 | ||||
| 	cl := cluster.New(ctrl.makeClusterConfig(), ctrl.KubeClient, *pgSpec, lg) | ||||
| 	cl.Run(ctrl.stopCh) | ||||
| 	teamName := strings.ToLower(cl.Spec.TeamID) | ||||
| 
 | ||||
| 	defer c.clustersMu.Unlock() | ||||
| 	c.clustersMu.Lock() | ||||
| 	defer ctrl.clustersMu.Unlock() | ||||
| 	ctrl.clustersMu.Lock() | ||||
| 
 | ||||
| 	c.teamClusters[teamName] = append(c.teamClusters[teamName], clusterName) | ||||
| 	c.clusters[clusterName] = cl | ||||
| 	c.clusterLogs[clusterName] = ringlog.New(c.opConfig.RingLogLines) | ||||
| 	c.clusterHistory[clusterName] = ringlog.New(c.opConfig.ClusterHistoryEntries) | ||||
| 	ctrl.teamClusters[teamName] = append(ctrl.teamClusters[teamName], clusterName) | ||||
| 	ctrl.clusters[clusterName] = cl | ||||
| 	ctrl.clusterLogs[clusterName] = ringlog.New(ctrl.opConfig.RingLogLines) | ||||
| 	ctrl.clusterHistory[clusterName] = ringlog.New(ctrl.opConfig.ClusterHistoryEntries) | ||||
| 
 | ||||
| 	return cl | ||||
| } | ||||
|  | @ -182,7 +184,7 @@ func (c *Controller) generatePlan(event ClusterEvent) cluster.Plan { | |||
| 	case EventAdd: | ||||
| 		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) | ||||
| 		return newCluster.PlanForCreate() | ||||
| 
 | ||||
|  | @ -272,7 +274,7 @@ func (c *Controller) processEvent(event ClusterEvent) { | |||
| 
 | ||||
| 		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) | ||||
| 
 | ||||
|  | @ -341,7 +343,7 @@ func (c *Controller) processEvent(event ClusterEvent) { | |||
| 
 | ||||
| 		// no race condition because a cluster is always processed by single worker
 | ||||
| 		if !clusterFound { | ||||
| 			cl = c.addCluster(lg, clusterName, event.NewSpec) | ||||
| 			cl = c.clusterFactory.addCluster(c, lg, clusterName, event.NewSpec) | ||||
| 		} | ||||
| 
 | ||||
| 		c.curWorkerCluster.Store(event.WorkerID, cl) | ||||
|  |  | |||
|  | @ -1,20 +1,101 @@ | |||
| package controller | ||||
| 
 | ||||
| import ( | ||||
| 	acidv1 "github.com/zalando-incubator/postgres-operator/pkg/apis/acid.zalan.do/v1" | ||||
| 	"github.com/zalando-incubator/postgres-operator/pkg/spec" | ||||
| 	"reflect" | ||||
| 	"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 ( | ||||
| 	True  = true | ||||
| 	False = false | ||||
| 	True   = true | ||||
| 	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) { | ||||
| 	c := NewController(&spec.ControllerConfig{}) | ||||
| 
 | ||||
| 	tests := []struct { | ||||
| 		name  string | ||||
| 		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 { | ||||
|     for _, b := range list { | ||||
|         if b == a { | ||||
|             return true | ||||
|         } | ||||
|     } | ||||
|     return false | ||||
| 	for _, b := range list { | ||||
| 		if b == a { | ||||
| 			return true | ||||
| 		} | ||||
| 	} | ||||
| 	return false | ||||
| } | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue