diff --git a/pkg/cluster/actions.go b/pkg/cluster/actions.go index 84cd2b65e..7ce026cf7 100644 --- a/pkg/cluster/actions.go +++ b/pkg/cluster/actions.go @@ -98,7 +98,8 @@ func (action UpdateSecret) Apply() error { if updateSecret { msg := "Updating the secret %q from the infrastructure roles" - cluster.logger.Debugf(msg, action.secret.Name) + name := util.NameFromMeta(action.secret.ObjectMeta) + cluster.logger.Debugf(msg, name) _, err := cluster.KubeClient. Secrets(action.secret.Namespace). diff --git a/pkg/cluster/actions_test.go b/pkg/cluster/actions_test.go new file mode 100644 index 000000000..bb4df408f --- /dev/null +++ b/pkg/cluster/actions_test.go @@ -0,0 +1,118 @@ +package cluster + +import ( + "testing" + + "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + v1core "k8s.io/client-go/kubernetes/typed/core/v1" + + "github.com/zalando-incubator/postgres-operator/pkg/spec" + "github.com/zalando-incubator/postgres-operator/pkg/util/k8sutil" +) + +var updateCalled = 0 + +type mockSecretGetter struct{} + +type testSecret struct { + v1core.SecretInterface +} + +func (c *testSecret) Update(secret *v1.Secret) (*v1.Secret, error) { + updateCalled += 1 + return secret, nil +} + +func (c *mockSecretGetter) Secrets(namespace string) v1core.SecretInterface { + return &testSecret{} +} + +func getMockK8sClient() k8sutil.KubernetesClient { + return k8sutil.KubernetesClient{ + SecretsGetter: &mockSecretGetter{}, + } +} + +func generateMockCluster(origin spec.RoleOrigin) *Cluster { + cluster := Cluster{ + KubeClient: getMockK8sClient(), + pgUsers: map[string]spec.PgUser{ + "testuser": { + Password: "123456", + Origin: origin, + }, + }, + } + + cluster.logger = logger. + WithField("pkg", "cluster"). + WithField("cluster-name", cluster.clusterName()) + + return &cluster +} + +func TestSecretValidation(t *testing.T) { + secret := v1.Secret{Data: make(map[string][]byte)} + + tests := []struct { + name string + action Action + checkErr func(error) bool + errMsg string + }{ + { + "Username for secret to update cannot be empty", + NewUpdateSecret("", &secret, nil), + func(err error) bool { return err == nil }, + "Empty username did not cause an error, expected %v, given %v", + }, + } + for _, tt := range tests { + result := tt.action.Validate() + if tt.checkErr(result) { + t.Errorf("%s: %v", tt.name, tt.errMsg) + } + } +} + +func TestSecretApply(t *testing.T) { + tests := []struct { + name string + action Action + checkErr func(error) bool + errMsg string + }{ + { + "Secret has been replaced with UpdateSecret for infrastructure role", + NewUpdateSecret("testuser", &v1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: "testsecret", + }, + Data: make(map[string][]byte), + }, generateMockCluster(spec.RoleOriginInfrastructure)), + func(err error) bool { return err != nil || updateCalled != 1 }, + "Update K8S client method was never called", + }, + { + "Secret has been synced with UpdateSecret for non infrastructure role", + NewUpdateSecret("testuser", &v1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: "testsecret", + }, + Data: make(map[string][]byte), + }, generateMockCluster(spec.RoleOriginSystem)), + func(err error) bool { return err != nil || updateCalled != 0 }, + "Update K8S client method was called, but should not be", + }, + } + for _, tt := range tests { + result := tt.action.Apply() + if tt.checkErr(result) { + t.Errorf("%s: %v", tt.name, tt.errMsg) + } + + // reset counters + updateCalled = 0 + } +}