196 lines
5.0 KiB
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)
|
|
}
|
|
}
|
|
}
|
|
}
|