Add credentials manager unit test in vSphere Cloud Provider
This commit is contained in:
		
							
								
								
									
										322
									
								
								pkg/cloudprovider/providers/vsphere/credentialmanager_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										322
									
								
								pkg/cloudprovider/providers/vsphere/credentialmanager_test.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,322 @@
 | 
				
			|||||||
 | 
					package vsphere
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"reflect"
 | 
				
			||||||
 | 
						"testing"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						corev1 "k8s.io/api/core/v1"
 | 
				
			||||||
 | 
						metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 | 
				
			||||||
 | 
						"k8s.io/apimachinery/pkg/labels"
 | 
				
			||||||
 | 
						"k8s.io/client-go/informers"
 | 
				
			||||||
 | 
						"k8s.io/client-go/kubernetes/fake"
 | 
				
			||||||
 | 
						"k8s.io/kubernetes/pkg/controller"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestSecretCredentialManager_GetCredential(t *testing.T) {
 | 
				
			||||||
 | 
						var (
 | 
				
			||||||
 | 
							userKey             = "username"
 | 
				
			||||||
 | 
							passwordKey         = "password"
 | 
				
			||||||
 | 
							testUser            = "user"
 | 
				
			||||||
 | 
							testPassword        = "password"
 | 
				
			||||||
 | 
							testServer          = "0.0.0.0"
 | 
				
			||||||
 | 
							testServer2         = "0.0.1.1"
 | 
				
			||||||
 | 
							testUserServer2     = "user1"
 | 
				
			||||||
 | 
							testPasswordServer2 = "password1"
 | 
				
			||||||
 | 
							testIncorrectServer = "1.1.1.1"
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
						var (
 | 
				
			||||||
 | 
							secretName      = "vsconf"
 | 
				
			||||||
 | 
							secretNamespace = "kube-system"
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
						var (
 | 
				
			||||||
 | 
							addSecretOp      = "ADD_SECRET_OP"
 | 
				
			||||||
 | 
							getCredentialsOp = "GET_CREDENTIAL_OP"
 | 
				
			||||||
 | 
							deleteSecretOp   = "DELETE_SECRET_OP"
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
						type GetCredentialsTest struct {
 | 
				
			||||||
 | 
							server   string
 | 
				
			||||||
 | 
							username string
 | 
				
			||||||
 | 
							password string
 | 
				
			||||||
 | 
							err      error
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						type OpSecretTest struct {
 | 
				
			||||||
 | 
							secret *corev1.Secret
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						type testEnv struct {
 | 
				
			||||||
 | 
							testName       string
 | 
				
			||||||
 | 
							ops            []string
 | 
				
			||||||
 | 
							expectedValues []interface{}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						client := &fake.Clientset{}
 | 
				
			||||||
 | 
						metaObj := metav1.ObjectMeta{
 | 
				
			||||||
 | 
							Name:      secretName,
 | 
				
			||||||
 | 
							Namespace: secretNamespace,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						defaultSecret := &corev1.Secret{
 | 
				
			||||||
 | 
							ObjectMeta: metaObj,
 | 
				
			||||||
 | 
							Data: map[string][]byte{
 | 
				
			||||||
 | 
								testServer + "." + userKey:     []byte(testUser),
 | 
				
			||||||
 | 
								testServer + "." + passwordKey: []byte(testPassword),
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						multiVCSecret := &corev1.Secret{
 | 
				
			||||||
 | 
							ObjectMeta: metaObj,
 | 
				
			||||||
 | 
							Data: map[string][]byte{
 | 
				
			||||||
 | 
								testServer + "." + userKey:      []byte(testUser),
 | 
				
			||||||
 | 
								testServer + "." + passwordKey:  []byte(testPassword),
 | 
				
			||||||
 | 
								testServer2 + "." + userKey:     []byte(testUserServer2),
 | 
				
			||||||
 | 
								testServer2 + "." + passwordKey: []byte(testPasswordServer2),
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						emptySecret := &corev1.Secret{
 | 
				
			||||||
 | 
							ObjectMeta: metaObj,
 | 
				
			||||||
 | 
							Data:       map[string][]byte{},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						tests := []testEnv{
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								testName: "Deleting secret should give the credentials from cache",
 | 
				
			||||||
 | 
								ops:      []string{addSecretOp, getCredentialsOp, deleteSecretOp, getCredentialsOp},
 | 
				
			||||||
 | 
								expectedValues: []interface{}{
 | 
				
			||||||
 | 
									OpSecretTest{
 | 
				
			||||||
 | 
										secret: defaultSecret,
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
									GetCredentialsTest{
 | 
				
			||||||
 | 
										username: testUser,
 | 
				
			||||||
 | 
										password: testPassword,
 | 
				
			||||||
 | 
										server:   testServer,
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
									OpSecretTest{
 | 
				
			||||||
 | 
										secret: defaultSecret,
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
									GetCredentialsTest{
 | 
				
			||||||
 | 
										username: testUser,
 | 
				
			||||||
 | 
										password: testPassword,
 | 
				
			||||||
 | 
										server:   testServer,
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								testName: "Add secret and get credentials",
 | 
				
			||||||
 | 
								ops:      []string{addSecretOp, getCredentialsOp},
 | 
				
			||||||
 | 
								expectedValues: []interface{}{
 | 
				
			||||||
 | 
									OpSecretTest{
 | 
				
			||||||
 | 
										secret: defaultSecret,
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
									GetCredentialsTest{
 | 
				
			||||||
 | 
										username: testUser,
 | 
				
			||||||
 | 
										password: testPassword,
 | 
				
			||||||
 | 
										server:   testServer,
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								testName: "Getcredentials should fail by not adding at secret at first time",
 | 
				
			||||||
 | 
								ops:      []string{getCredentialsOp},
 | 
				
			||||||
 | 
								expectedValues: []interface{}{
 | 
				
			||||||
 | 
									GetCredentialsTest{
 | 
				
			||||||
 | 
										username: testUser,
 | 
				
			||||||
 | 
										password: testPassword,
 | 
				
			||||||
 | 
										server:   testServer,
 | 
				
			||||||
 | 
										err:      ErrCredentialsNotFound,
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								testName: "GetCredential should fail to get credentials from empty secrets",
 | 
				
			||||||
 | 
								ops:      []string{addSecretOp, getCredentialsOp},
 | 
				
			||||||
 | 
								expectedValues: []interface{}{
 | 
				
			||||||
 | 
									OpSecretTest{
 | 
				
			||||||
 | 
										secret: emptySecret,
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
									GetCredentialsTest{
 | 
				
			||||||
 | 
										server: testServer,
 | 
				
			||||||
 | 
										err:    ErrCredentialMissing,
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								testName: "GetCredential should fail to get credentials for invalid server",
 | 
				
			||||||
 | 
								ops:      []string{addSecretOp, getCredentialsOp},
 | 
				
			||||||
 | 
								expectedValues: []interface{}{
 | 
				
			||||||
 | 
									OpSecretTest{
 | 
				
			||||||
 | 
										secret: defaultSecret,
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
									GetCredentialsTest{
 | 
				
			||||||
 | 
										server: testIncorrectServer,
 | 
				
			||||||
 | 
										err:    ErrCredentialsNotFound,
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								testName: "GetCredential for multi-vc",
 | 
				
			||||||
 | 
								ops:      []string{addSecretOp, getCredentialsOp},
 | 
				
			||||||
 | 
								expectedValues: []interface{}{
 | 
				
			||||||
 | 
									OpSecretTest{
 | 
				
			||||||
 | 
										secret: multiVCSecret,
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
									GetCredentialsTest{
 | 
				
			||||||
 | 
										server:   testServer2,
 | 
				
			||||||
 | 
										username: testUserServer2,
 | 
				
			||||||
 | 
										password: testPasswordServer2,
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						informerFactory := informers.NewSharedInformerFactory(client, controller.NoResyncPeriodFunc())
 | 
				
			||||||
 | 
						secretInformer := informerFactory.Core().V1().Secrets()
 | 
				
			||||||
 | 
						secretCredentialManager := &SecretCredentialManager{
 | 
				
			||||||
 | 
							SecretName:      secretName,
 | 
				
			||||||
 | 
							SecretNamespace: secretNamespace,
 | 
				
			||||||
 | 
							SecretLister:    secretInformer.Lister(),
 | 
				
			||||||
 | 
							Cache: &SecretCache{
 | 
				
			||||||
 | 
								VirtualCenter: make(map[string]*Credential),
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						cleanupSecretCredentialManager := func() {
 | 
				
			||||||
 | 
							secretCredentialManager.Cache.Secret = nil
 | 
				
			||||||
 | 
							for key := range secretCredentialManager.Cache.VirtualCenter {
 | 
				
			||||||
 | 
								delete(secretCredentialManager.Cache.VirtualCenter, key)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							secrets, err := secretCredentialManager.SecretLister.List(labels.Everything())
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								t.Fatal("Failed to get all secrets from sharedInformer. error: ", err)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							for _, secret := range secrets {
 | 
				
			||||||
 | 
								secretInformer.Informer().GetIndexer().Delete(secret)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for _, test := range tests {
 | 
				
			||||||
 | 
							t.Logf("Executing Testcase: %s", test.testName)
 | 
				
			||||||
 | 
							for ntest, op := range test.ops {
 | 
				
			||||||
 | 
								switch op {
 | 
				
			||||||
 | 
								case addSecretOp:
 | 
				
			||||||
 | 
									expected := test.expectedValues[ntest].(OpSecretTest)
 | 
				
			||||||
 | 
									t.Logf("Adding secret: %s", expected.secret)
 | 
				
			||||||
 | 
									err := secretInformer.Informer().GetIndexer().Add(expected.secret)
 | 
				
			||||||
 | 
									if err != nil {
 | 
				
			||||||
 | 
										t.Fatalf("Failed to add secret to internal cache: %v", err)
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								case getCredentialsOp:
 | 
				
			||||||
 | 
									expected := test.expectedValues[ntest].(GetCredentialsTest)
 | 
				
			||||||
 | 
									credential, err := secretCredentialManager.GetCredential(expected.server)
 | 
				
			||||||
 | 
									t.Logf("Retrieving credentials for server %s", expected.server)
 | 
				
			||||||
 | 
									if err != expected.err {
 | 
				
			||||||
 | 
										t.Fatalf("Fail to get credentials with error: %v", err)
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									if expected.err == nil {
 | 
				
			||||||
 | 
										if expected.username != credential.User ||
 | 
				
			||||||
 | 
											expected.password != credential.Password {
 | 
				
			||||||
 | 
											t.Fatalf("Recieved credentials %v "+
 | 
				
			||||||
 | 
												"are diffrent than actual credential user:%s password:%s", credential, expected.username,
 | 
				
			||||||
 | 
												expected.password)
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								case deleteSecretOp:
 | 
				
			||||||
 | 
									expected := test.expectedValues[ntest].(OpSecretTest)
 | 
				
			||||||
 | 
									t.Logf("Deleting secret: %s", expected.secret)
 | 
				
			||||||
 | 
									err := secretInformer.Informer().GetIndexer().Delete(expected.secret)
 | 
				
			||||||
 | 
									if err != nil {
 | 
				
			||||||
 | 
										t.Fatalf("Failed to delete secret to internal cache: %v", err)
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							cleanupSecretCredentialManager()
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestParseSecretConfig(t *testing.T) {
 | 
				
			||||||
 | 
						var (
 | 
				
			||||||
 | 
							testUsername = "Admin"
 | 
				
			||||||
 | 
							testPassword = "Password"
 | 
				
			||||||
 | 
							testIP       = "10.20.30.40"
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
						var testcases = []struct {
 | 
				
			||||||
 | 
							testName      string
 | 
				
			||||||
 | 
							data          map[string][]byte
 | 
				
			||||||
 | 
							config        map[string]*Credential
 | 
				
			||||||
 | 
							expectedError error
 | 
				
			||||||
 | 
						}{
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								testName: "Valid username and password",
 | 
				
			||||||
 | 
								data: map[string][]byte{
 | 
				
			||||||
 | 
									"10.20.30.40.username": []byte(testUsername),
 | 
				
			||||||
 | 
									"10.20.30.40.password": []byte(testPassword),
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								config: map[string]*Credential{
 | 
				
			||||||
 | 
									testIP: {
 | 
				
			||||||
 | 
										User:     testUsername,
 | 
				
			||||||
 | 
										Password: testPassword,
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								expectedError: nil,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								testName: "Invalid username key with valid password key",
 | 
				
			||||||
 | 
								data: map[string][]byte{
 | 
				
			||||||
 | 
									"10.20.30.40.usernam":  []byte(testUsername),
 | 
				
			||||||
 | 
									"10.20.30.40.password": []byte(testPassword),
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								config:        nil,
 | 
				
			||||||
 | 
								expectedError: ErrUnknownSecretKey,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								testName: "Missing username",
 | 
				
			||||||
 | 
								data: map[string][]byte{
 | 
				
			||||||
 | 
									"10.20.30.40.password": []byte(testPassword),
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								config: map[string]*Credential{
 | 
				
			||||||
 | 
									testIP: {
 | 
				
			||||||
 | 
										Password: testPassword,
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								expectedError: ErrCredentialMissing,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								testName: "Missing password",
 | 
				
			||||||
 | 
								data: map[string][]byte{
 | 
				
			||||||
 | 
									"10.20.30.40.username": []byte(testUsername),
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								config: map[string]*Credential{
 | 
				
			||||||
 | 
									testIP: {
 | 
				
			||||||
 | 
										User: testUsername,
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								expectedError: ErrCredentialMissing,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								testName: "IP with unknown key",
 | 
				
			||||||
 | 
								data: map[string][]byte{
 | 
				
			||||||
 | 
									"10.20.30.40": []byte(testUsername),
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								config:        nil,
 | 
				
			||||||
 | 
								expectedError: ErrUnknownSecretKey,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						resultConfig := make(map[string]*Credential)
 | 
				
			||||||
 | 
						cleanupResultConfig := func(config map[string]*Credential) {
 | 
				
			||||||
 | 
							for k := range config {
 | 
				
			||||||
 | 
								delete(config, k)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for _, testcase := range testcases {
 | 
				
			||||||
 | 
							err := parseConfig(testcase.data, resultConfig)
 | 
				
			||||||
 | 
							t.Logf("Executing Testcase: %s", testcase.testName)
 | 
				
			||||||
 | 
							if err != testcase.expectedError {
 | 
				
			||||||
 | 
								t.Fatalf("Parsing Secret failed for data %+v: %s", testcase.data, err)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if testcase.config != nil && !reflect.DeepEqual(testcase.config, resultConfig) {
 | 
				
			||||||
 | 
								t.Fatalf("Parsing Secret failed for data %+v expected config %+v and actual config %+v",
 | 
				
			||||||
 | 
									testcase.data, resultConfig, testcase.config)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							cleanupResultConfig(resultConfig)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Reference in New Issue
	
	Block a user