package cluster import ( acidv1 "github.com/zalando-incubator/postgres-operator/pkg/apis/acid.zalan.do/v1" "github.com/zalando-incubator/postgres-operator/pkg/util/config" "github.com/zalando-incubator/postgres-operator/pkg/util/k8sutil" "reflect" "testing" policyv1beta1 "k8s.io/api/policy/v1beta1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/intstr" ) func True() *bool { b := true return &b } func False() *bool { b := false return &b } func toIntStr(val int) *intstr.IntOrString { b := intstr.FromInt(val) return &b } func TestCreateLoadBalancerLogic(t *testing.T) { var cluster = New( Config{ OpConfig: config.Config{ ProtectedRoles: []string{"admin"}, Auth: config.Auth{ SuperUsername: superUserName, ReplicationUsername: replicationUserName, }, }, }, k8sutil.KubernetesClient{}, acidv1.Postgresql{}, logger) testName := "TestCreateLoadBalancerLogic" tests := []struct { subtest string role PostgresRole spec *acidv1.PostgresSpec opConfig config.Config result bool }{ { subtest: "new format, load balancer is enabled for replica", role: Replica, spec: &acidv1.PostgresSpec{EnableReplicaLoadBalancer: True()}, opConfig: config.Config{}, result: true, }, { subtest: "new format, load balancer is disabled for replica", role: Replica, spec: &acidv1.PostgresSpec{EnableReplicaLoadBalancer: False()}, opConfig: config.Config{}, result: false, }, { subtest: "new format, load balancer isn't specified for replica", role: Replica, spec: &acidv1.PostgresSpec{EnableReplicaLoadBalancer: nil}, opConfig: config.Config{EnableReplicaLoadBalancer: true}, result: true, }, { subtest: "new format, load balancer isn't specified for replica", role: Replica, spec: &acidv1.PostgresSpec{EnableReplicaLoadBalancer: nil}, opConfig: config.Config{EnableReplicaLoadBalancer: false}, result: false, }, } for _, tt := range tests { cluster.OpConfig = tt.opConfig result := cluster.shouldCreateLoadBalancerForService(tt.role, tt.spec) if tt.result != result { t.Errorf("%s %s: Load balancer is %t, expect %t for role %#v and spec %#v", testName, tt.subtest, result, tt.result, tt.role, tt.spec) } } } func TestGeneratePodDisruptionBudget(t *testing.T) { tests := []struct { c *Cluster out policyv1beta1.PodDisruptionBudget }{ // With multiple instances. { New( Config{OpConfig: config.Config{Resources: config.Resources{ClusterNameLabel: "cluster-name", PodRoleLabel: "spilo-role"}, PDBNameFormat: "postgres-{cluster}-pdb"}}, k8sutil.KubernetesClient{}, acidv1.Postgresql{ ObjectMeta: metav1.ObjectMeta{Name: "myapp-database", Namespace: "myapp"}, Spec: acidv1.PostgresSpec{TeamID: "myapp", NumberOfInstances: 3}}, logger), policyv1beta1.PodDisruptionBudget{ ObjectMeta: metav1.ObjectMeta{ Name: "postgres-myapp-database-pdb", Namespace: "myapp", Labels: map[string]string{"team": "myapp", "cluster-name": "myapp-database"}, }, Spec: policyv1beta1.PodDisruptionBudgetSpec{ MinAvailable: toIntStr(1), Selector: &metav1.LabelSelector{ MatchLabels: map[string]string{"spilo-role": "master", "cluster-name": "myapp-database"}, }, }, }, }, // With zero instances. { New( Config{OpConfig: config.Config{Resources: config.Resources{ClusterNameLabel: "cluster-name", PodRoleLabel: "spilo-role"}, PDBNameFormat: "postgres-{cluster}-pdb"}}, k8sutil.KubernetesClient{}, acidv1.Postgresql{ ObjectMeta: metav1.ObjectMeta{Name: "myapp-database", Namespace: "myapp"}, Spec: acidv1.PostgresSpec{TeamID: "myapp", NumberOfInstances: 0}}, logger), policyv1beta1.PodDisruptionBudget{ ObjectMeta: metav1.ObjectMeta{ Name: "postgres-myapp-database-pdb", Namespace: "myapp", Labels: map[string]string{"team": "myapp", "cluster-name": "myapp-database"}, }, Spec: policyv1beta1.PodDisruptionBudgetSpec{ MinAvailable: toIntStr(0), Selector: &metav1.LabelSelector{ MatchLabels: map[string]string{"spilo-role": "master", "cluster-name": "myapp-database"}, }, }, }, }, // With AllowMasterDisruption. { New( Config{OpConfig: config.Config{Resources: config.Resources{ClusterNameLabel: "cluster-name", PodRoleLabel: "spilo-role"}, PDBNameFormat: "postgres-{cluster}-pdb"}}, k8sutil.KubernetesClient{}, acidv1.Postgresql{ ObjectMeta: metav1.ObjectMeta{Name: "myapp-database", Namespace: "myapp"}, Spec: acidv1.PostgresSpec{TeamID: "myapp", NumberOfInstances: 3, AllowMasterDisruption: true}}, logger), policyv1beta1.PodDisruptionBudget{ ObjectMeta: metav1.ObjectMeta{ Name: "postgres-myapp-database-pdb", Namespace: "myapp", Labels: map[string]string{"team": "myapp", "cluster-name": "myapp-database"}, }, Spec: policyv1beta1.PodDisruptionBudgetSpec{ MinAvailable: toIntStr(0), Selector: &metav1.LabelSelector{ MatchLabels: map[string]string{"spilo-role": "master", "cluster-name": "myapp-database"}, }, }, }, }, // With non-default PDBNameFormat. { New( Config{OpConfig: config.Config{Resources: config.Resources{ClusterNameLabel: "cluster-name", PodRoleLabel: "spilo-role"}, PDBNameFormat: "postgres-{cluster}-databass-budget"}}, k8sutil.KubernetesClient{}, acidv1.Postgresql{ ObjectMeta: metav1.ObjectMeta{Name: "myapp-database", Namespace: "myapp"}, Spec: acidv1.PostgresSpec{TeamID: "myapp", NumberOfInstances: 3}}, logger), policyv1beta1.PodDisruptionBudget{ ObjectMeta: metav1.ObjectMeta{ Name: "postgres-myapp-database-databass-budget", Namespace: "myapp", Labels: map[string]string{"team": "myapp", "cluster-name": "myapp-database"}, }, Spec: policyv1beta1.PodDisruptionBudgetSpec{ MinAvailable: toIntStr(1), Selector: &metav1.LabelSelector{ MatchLabels: map[string]string{"spilo-role": "master", "cluster-name": "myapp-database"}, }, }, }, }, } for _, tt := range tests { result := tt.c.generatePodDisruptionBudget() if !reflect.DeepEqual(*result, tt.out) { t.Errorf("Expected PodDisruptionBudget: %#v, got %#v", tt.out, *result) } } }