postgres-operator/pkg/controller/postgresql_test.go

196 lines
5.0 KiB
Go

package controller
import (
"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
)
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 mockSecretGetter struct{}
type testNoSecret struct {
v1core.SecretInterface
}
type testSecret struct {
v1core.SecretInterface
}
func (c *testNoSecret) Get(name string, options metav1.GetOptions) (*v1.Secret, error) {
return nil, &NotFoundError{}
}
func (c *testSecret) Get(name string, options metav1.GetOptions) (*v1.Secret, error) {
return &v1.Secret{}, nil
}
func (c *mockNoSecretGetter) Secrets(namespace string) v1core.SecretInterface {
return &testNoSecret{}
}
func (c *mockSecretGetter) Secrets(namespace string) v1core.SecretInterface {
return &testSecret{}
}
func mockK8sClientNoSecrets() k8sutil.KubernetesClient {
return k8sutil.KubernetesClient{
SecretsGetter: &mockNoSecretGetter{},
}
}
func mockK8sClient() k8sutil.KubernetesClient {
return k8sutil.KubernetesClient{
SecretsGetter: &mockSecretGetter{},
}
}
func TestMergeDeprecatedPostgreSQLSpecParameters(t *testing.T) {
c := NewController(&spec.ControllerConfig{})
tests := []struct {
name string
in *acidv1.PostgresSpec
out *acidv1.PostgresSpec
error string
}{
{
"Check that old parameters propagate values to the new ones",
&acidv1.PostgresSpec{UseLoadBalancer: &True, ReplicaLoadBalancer: &True},
&acidv1.PostgresSpec{UseLoadBalancer: nil, ReplicaLoadBalancer: nil,
EnableMasterLoadBalancer: &True, EnableReplicaLoadBalancer: &True},
"New parameters should be set from the values of old ones",
},
{
"Check that new parameters are not set when both old and new ones are present",
&acidv1.PostgresSpec{UseLoadBalancer: &True, EnableMasterLoadBalancer: &False},
&acidv1.PostgresSpec{UseLoadBalancer: nil, EnableMasterLoadBalancer: &False},
"New parameters should remain unchanged when both old and new are present",
},
}
for _, tt := range tests {
result := c.mergeDeprecatedPostgreSQLSpecParameters(tt.in)
if !reflect.DeepEqual(result, tt.out) {
t.Errorf("%s: %v", tt.name, tt.error)
}
}
}
func TestGeneratePlan(t *testing.T) {
c := NewController(&spec.ControllerConfig{})
c.opConfig.SuperUsername = "test-superuser"
c.opConfig.SecretNameTemplate = "secret"
c.clusterFactory = &mockClusterGenerator{}
tests := []struct {
name string
client k8sutil.KubernetesClient
in ClusterEvent
contains cluster.Plan
error string
}{
{
"Cluster add produces plan with a CreateSecret",
mockK8sClientNoSecrets(),
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",
},
{
"Cluster add produces plan with an UpdateSecret if they're exist",
mockK8sClient(),
ClusterEvent{
EventType: EventAdd,
NewSpec: &acidv1.Postgresql{
ObjectMeta: metav1.ObjectMeta{
Name: "TestCluster",
Namespace: "TestNamespace",
},
},
},
[]cluster.Action{cluster.UpdateSecret{}, cluster.UpdateSecret{}},
"A plan for a new cluster should create secrets",
},
}
for _, tt := range tests {
c.KubeClient = tt.client
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)
}
}
}
}