...

Source file src/github.com/redhat-developer/odo/pkg/dev/kubedev/storage/utils_test.go

Documentation: github.com/redhat-developer/odo/pkg/dev/kubedev/storage

     1  package storage
     2  
     3  import (
     4  	"fmt"
     5  	"testing"
     6  
     7  	devfilev1 "github.com/devfile/api/v2/pkg/apis/workspaces/v1alpha2"
     8  	"github.com/devfile/api/v2/pkg/attributes"
     9  	"github.com/devfile/library/v2/pkg/devfile/generator"
    10  	devfileParser "github.com/devfile/library/v2/pkg/devfile/parser"
    11  	"github.com/devfile/library/v2/pkg/devfile/parser/data"
    12  	parsercommon "github.com/devfile/library/v2/pkg/devfile/parser/data/v2/common"
    13  	"github.com/golang/mock/gomock"
    14  	"github.com/google/go-cmp/cmp"
    15  	"github.com/redhat-developer/odo/pkg/configAutomount"
    16  	"github.com/redhat-developer/odo/pkg/testingutil"
    17  	corev1 "k8s.io/api/core/v1"
    18  	v1 "k8s.io/api/core/v1"
    19  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    20  	"k8s.io/utils/pointer"
    21  )
    22  
    23  func TestGetPVC(t *testing.T) {
    24  
    25  	tests := []struct {
    26  		pvc        string
    27  		volumeName string
    28  	}{
    29  		{
    30  			pvc:        "mypvc",
    31  			volumeName: "myvolume",
    32  		},
    33  	}
    34  
    35  	for _, tt := range tests {
    36  		t.Run(tt.volumeName, func(t *testing.T) {
    37  			volume := getPVC(tt.volumeName, tt.pvc)
    38  
    39  			if volume.Name != tt.volumeName {
    40  				t.Errorf("TestGetPVC error: volume name does not match; expected %s got %s", tt.volumeName, volume.Name)
    41  			}
    42  
    43  			if volume.PersistentVolumeClaim.ClaimName != tt.pvc {
    44  				t.Errorf("TestGetPVC error: pvc name does not match; expected %s got %s", tt.pvc, volume.PersistentVolumeClaim.ClaimName)
    45  			}
    46  		})
    47  	}
    48  }
    49  
    50  func TestGetVolumeInfos(t *testing.T) {
    51  	tests := []struct {
    52  		name                 string
    53  		pvcs                 []corev1.PersistentVolumeClaim
    54  		wantOdoSourcePVCName string
    55  		wantInfos            map[string]VolumeInfo
    56  		wantErr              bool
    57  	}{
    58  		{
    59  			name: "odo-projects is not found",
    60  			pvcs: []corev1.PersistentVolumeClaim{
    61  				{
    62  					ObjectMeta: metav1.ObjectMeta{
    63  						Name: "pvc1",
    64  						Labels: map[string]string{
    65  							"app.kubernetes.io/storage-name": "a-name",
    66  						},
    67  					},
    68  				},
    69  			},
    70  			wantOdoSourcePVCName: "",
    71  			wantInfos: map[string]VolumeInfo{
    72  				"a-name": {
    73  					PVCName:    "pvc1",
    74  					VolumeName: "pvc1-vol",
    75  				},
    76  			},
    77  		},
    78  		{
    79  			name: "odo-projects is found",
    80  			pvcs: []corev1.PersistentVolumeClaim{
    81  				{
    82  					ObjectMeta: metav1.ObjectMeta{
    83  						Name: "pvc1",
    84  						Labels: map[string]string{
    85  							"app.kubernetes.io/storage-name": "odo-projects",
    86  						},
    87  					},
    88  				},
    89  			},
    90  			wantOdoSourcePVCName: "pvc1",
    91  			wantInfos:            map[string]VolumeInfo{},
    92  		},
    93  		{
    94  			name: "odo-projects is found and other pvcs",
    95  			pvcs: []corev1.PersistentVolumeClaim{
    96  				{
    97  					ObjectMeta: metav1.ObjectMeta{
    98  						Name: "pvc1",
    99  						Labels: map[string]string{
   100  							"app.kubernetes.io/storage-name": "odo-projects",
   101  						},
   102  					},
   103  				},
   104  				{
   105  					ObjectMeta: metav1.ObjectMeta{
   106  						Name: "pvc2",
   107  						Labels: map[string]string{
   108  							"app.kubernetes.io/storage-name": "name2",
   109  						},
   110  					},
   111  				},
   112  				{
   113  					ObjectMeta: metav1.ObjectMeta{
   114  						Name: "pvc3",
   115  						Labels: map[string]string{
   116  							"app.kubernetes.io/storage-name": "name3",
   117  						},
   118  					},
   119  				},
   120  			},
   121  			wantOdoSourcePVCName: "pvc1",
   122  			wantInfos: map[string]VolumeInfo{
   123  				"name2": {
   124  					PVCName:    "pvc2",
   125  					VolumeName: "pvc2-vol",
   126  				},
   127  				"name3": {
   128  					PVCName:    "pvc3",
   129  					VolumeName: "pvc3-vol",
   130  				},
   131  			},
   132  		},
   133  	}
   134  
   135  	for _, tt := range tests {
   136  		t.Run(tt.name, func(t *testing.T) {
   137  			odoSourcePVCName, infos, err := GetVolumeInfos(tt.pvcs)
   138  			if err != nil != tt.wantErr {
   139  				t.Errorf("Got error %v, expected %v", err, tt.wantErr)
   140  				return
   141  			}
   142  			if err != nil {
   143  				return
   144  			}
   145  			if diff := cmp.Diff(tt.wantOdoSourcePVCName, odoSourcePVCName); diff != "" {
   146  				t.Errorf("GetVolumeInfos() wantOdoSourcePVCName mismatch (-want +got):\n%s", diff)
   147  			}
   148  			if diff := cmp.Diff(tt.wantInfos, infos); diff != "" {
   149  				t.Errorf("GetVolumeInfos() wantInfos mismatch (-want +got):\n%s", diff)
   150  			}
   151  		})
   152  	}
   153  }
   154  
   155  func TestAddVolumeMountToContainers(t *testing.T) {
   156  
   157  	tests := []struct {
   158  		podName                string
   159  		namespace              string
   160  		serviceAccount         string
   161  		pvc                    string
   162  		volumeName             string
   163  		containerMountPathsMap map[string][]string
   164  		container              v1.Container
   165  		labels                 map[string]string
   166  		wantErr                bool
   167  	}{
   168  		{
   169  			podName:        "podSpecTest",
   170  			namespace:      "default",
   171  			serviceAccount: "default",
   172  			pvc:            "mypvc",
   173  			volumeName:     "myvolume",
   174  			containerMountPathsMap: map[string][]string{
   175  				"container1": {"/tmp/path1", "/tmp/path2"},
   176  			},
   177  			container: v1.Container{
   178  				Name:            "container1",
   179  				Image:           "image1",
   180  				ImagePullPolicy: v1.PullAlways,
   181  
   182  				Command: []string{"tail"},
   183  				Args:    []string{"-f", "/dev/null"},
   184  				Env:     []v1.EnvVar{},
   185  			},
   186  			labels: map[string]string{
   187  				"app":       "app",
   188  				"component": "frontend",
   189  			},
   190  			wantErr: false,
   191  		},
   192  		{
   193  			podName:        "podSpecTest",
   194  			namespace:      "default",
   195  			serviceAccount: "default",
   196  			pvc:            "mypvc",
   197  			volumeName:     "myvolume",
   198  			containerMountPathsMap: map[string][]string{
   199  				"container1": {"/tmp/path1", "/tmp/path2"},
   200  			},
   201  			container: v1.Container{},
   202  			labels: map[string]string{
   203  				"app":       "app",
   204  				"component": "frontend",
   205  			},
   206  			wantErr: true,
   207  		},
   208  	}
   209  
   210  	for _, tt := range tests {
   211  		t.Run(tt.podName, func(t *testing.T) {
   212  			containers := []v1.Container{tt.container}
   213  			initContainers := []v1.Container{}
   214  			addVolumeMountToContainers(containers, initContainers, tt.volumeName, tt.containerMountPathsMap)
   215  
   216  			mountPathCount := 0
   217  			for _, container := range containers {
   218  				if container.Name == tt.container.Name {
   219  					for _, volumeMount := range container.VolumeMounts {
   220  						if volumeMount.Name == tt.volumeName {
   221  							for _, mountPath := range tt.containerMountPathsMap[tt.container.Name] {
   222  								if volumeMount.MountPath == mountPath {
   223  									mountPathCount++
   224  								}
   225  							}
   226  						}
   227  					}
   228  				}
   229  			}
   230  
   231  			if mountPathCount != len(tt.containerMountPathsMap[tt.container.Name]) {
   232  				t.Errorf("Volume Mounts for %s have not been properly mounted to the container", tt.volumeName)
   233  			}
   234  		})
   235  	}
   236  }
   237  
   238  func TestGetVolumesAndVolumeMounts(t *testing.T) {
   239  
   240  	type testVolumeMountInfo struct {
   241  		mountPath  string
   242  		volumeName string
   243  	}
   244  
   245  	tests := []struct {
   246  		name                string
   247  		components          []devfilev1.Component
   248  		volumeNameToVolInfo map[string]VolumeInfo
   249  		wantContainerToVol  map[string][]testVolumeMountInfo
   250  		wantErr             bool
   251  	}{
   252  		{
   253  			name:       "One volume mounted",
   254  			components: []devfilev1.Component{testingutil.GetFakeContainerComponent("comp1"), testingutil.GetFakeContainerComponent("comp2")},
   255  			volumeNameToVolInfo: map[string]VolumeInfo{
   256  				"myvolume1": {
   257  					PVCName:    "volume1-pvc",
   258  					VolumeName: "volume1-pvc-vol",
   259  				},
   260  			},
   261  			wantContainerToVol: map[string][]testVolumeMountInfo{
   262  				"comp1": {
   263  					{
   264  						mountPath:  "/my/volume/mount/path1",
   265  						volumeName: "volume1-pvc-vol",
   266  					},
   267  				},
   268  				"comp2": {
   269  					{
   270  						mountPath:  "/my/volume/mount/path1",
   271  						volumeName: "volume1-pvc-vol",
   272  					},
   273  				},
   274  			},
   275  			wantErr: false,
   276  		},
   277  		{
   278  			name: "One volume mounted at diff locations",
   279  			components: []devfilev1.Component{
   280  				{
   281  					Name: "container1",
   282  					ComponentUnion: devfilev1.ComponentUnion{
   283  						Container: &devfilev1.ContainerComponent{
   284  							Container: devfilev1.Container{
   285  								VolumeMounts: []devfilev1.VolumeMount{
   286  									{
   287  										Name: "volume1",
   288  										Path: "/path1",
   289  									},
   290  									{
   291  										Name: "volume1",
   292  										Path: "/path2",
   293  									},
   294  								},
   295  							},
   296  						},
   297  					},
   298  				},
   299  			},
   300  			volumeNameToVolInfo: map[string]VolumeInfo{
   301  				"volume1": {
   302  					PVCName:    "volume1-pvc",
   303  					VolumeName: "volume1-pvc-vol",
   304  				},
   305  			},
   306  			wantContainerToVol: map[string][]testVolumeMountInfo{
   307  				"container1": {
   308  					{
   309  						mountPath:  "/path1",
   310  						volumeName: "volume1-pvc-vol",
   311  					},
   312  					{
   313  						mountPath:  "/path2",
   314  						volumeName: "volume1-pvc-vol",
   315  					},
   316  				},
   317  			},
   318  			wantErr: false,
   319  		},
   320  		{
   321  			name: "One volume mounted at diff container components",
   322  			components: []devfilev1.Component{
   323  				{
   324  					Name: "container1",
   325  					ComponentUnion: devfilev1.ComponentUnion{
   326  						Container: &devfilev1.ContainerComponent{
   327  							Container: devfilev1.Container{
   328  								VolumeMounts: []devfilev1.VolumeMount{
   329  									{
   330  										Name: "volume1",
   331  										Path: "/path1",
   332  									},
   333  								},
   334  							},
   335  						},
   336  					},
   337  				},
   338  				{
   339  					Name: "container2",
   340  					ComponentUnion: devfilev1.ComponentUnion{
   341  						Container: &devfilev1.ContainerComponent{
   342  							Container: devfilev1.Container{
   343  								VolumeMounts: []devfilev1.VolumeMount{
   344  									{
   345  										Name: "volume1",
   346  										Path: "/path2",
   347  									},
   348  								},
   349  							},
   350  						},
   351  					},
   352  				},
   353  			},
   354  			volumeNameToVolInfo: map[string]VolumeInfo{
   355  				"volume1": {
   356  					PVCName:    "volume1-pvc",
   357  					VolumeName: "volume1-pvc-vol",
   358  				},
   359  			},
   360  			wantContainerToVol: map[string][]testVolumeMountInfo{
   361  				"container1": {
   362  					{
   363  						mountPath:  "/path1",
   364  						volumeName: "volume1-pvc-vol",
   365  					},
   366  				},
   367  				"container2": {
   368  					{
   369  						mountPath:  "/path2",
   370  						volumeName: "volume1-pvc-vol",
   371  					},
   372  				},
   373  			},
   374  			wantErr: false,
   375  		},
   376  		{
   377  			name: "Invalid case",
   378  			components: []devfilev1.Component{
   379  				{
   380  					Name: "container1",
   381  					Attributes: attributes.Attributes{}.FromStringMap(map[string]string{
   382  						"firstString": "firstStringValue",
   383  					}),
   384  					ComponentUnion: devfilev1.ComponentUnion{},
   385  				},
   386  			},
   387  			wantErr: true,
   388  		},
   389  	}
   390  
   391  	for _, tt := range tests {
   392  		t.Run(tt.name, func(t *testing.T) {
   393  
   394  			devObj := devfileParser.DevfileObj{
   395  				Data: func() data.DevfileData {
   396  					devfileData, err := data.NewDevfileData(string(data.APISchemaVersion200))
   397  					if err != nil {
   398  						t.Error(err)
   399  					}
   400  					err = devfileData.AddComponents(tt.components)
   401  					if err != nil {
   402  						t.Error(err)
   403  					}
   404  					return devfileData
   405  				}(),
   406  			}
   407  
   408  			podTemplateSpec, err := generator.GetPodTemplateSpec(devObj, generator.PodTemplateParams{})
   409  			if !tt.wantErr && err != nil {
   410  				t.Errorf("TestGetVolumesAndVolumeMounts error - %v", err)
   411  				return
   412  			}
   413  
   414  			if tt.wantErr && err != nil {
   415  				return
   416  			}
   417  
   418  			containers := podTemplateSpec.Spec.Containers
   419  
   420  			var options parsercommon.DevfileOptions
   421  			if tt.wantErr {
   422  				options = parsercommon.DevfileOptions{
   423  					Filter: map[string]interface{}{
   424  						"firstString": "firstStringValue",
   425  					},
   426  				}
   427  			}
   428  
   429  			initContainers := []v1.Container{}
   430  			pvcVols, err := GetPersistentVolumesAndVolumeMounts(devObj, containers, initContainers, tt.volumeNameToVolInfo, options)
   431  			if !tt.wantErr && err != nil {
   432  				t.Errorf("TestGetVolumesAndVolumeMounts unexpected error: %v", err)
   433  				return
   434  			} else if tt.wantErr && err != nil {
   435  				return
   436  			} else if tt.wantErr && err == nil {
   437  				t.Error("TestGetVolumesAndVolumeMounts expected error but got nil")
   438  				return
   439  			}
   440  
   441  			// check if the pvc volumes returned are correct
   442  			for _, volInfo := range tt.volumeNameToVolInfo {
   443  				matched := false
   444  				for _, pvcVol := range pvcVols {
   445  					if volInfo.VolumeName == pvcVol.Name && pvcVol.PersistentVolumeClaim != nil && volInfo.PVCName == pvcVol.PersistentVolumeClaim.ClaimName {
   446  						matched = true
   447  					}
   448  				}
   449  
   450  				if !matched {
   451  					t.Errorf("TestGetVolumesAndVolumeMounts error - could not find volume details %s in the actual result", volInfo.VolumeName)
   452  				}
   453  			}
   454  
   455  			// check the volume mounts of the containers
   456  			for _, container := range containers {
   457  				if volMounts, ok := tt.wantContainerToVol[container.Name]; !ok {
   458  					t.Errorf("TestGetVolumesAndVolumeMounts error - did not find the expected container %s", container.Name)
   459  					return
   460  				} else {
   461  					for _, expectedVolMount := range volMounts {
   462  						matched := false
   463  						for _, actualVolMount := range container.VolumeMounts {
   464  							if expectedVolMount.volumeName == actualVolMount.Name && expectedVolMount.mountPath == actualVolMount.MountPath {
   465  								matched = true
   466  							}
   467  						}
   468  
   469  						if !matched {
   470  							t.Errorf("TestGetVolumesAndVolumeMounts error - could not find volume mount details for path %s in the actual result for container %s", expectedVolMount.mountPath, container.Name)
   471  						}
   472  					}
   473  				}
   474  			}
   475  		})
   476  	}
   477  }
   478  
   479  func TestGetAutomountVolumes(t *testing.T) {
   480  
   481  	container1 := corev1.Container{
   482  		Name:  "container1",
   483  		Image: "image1",
   484  	}
   485  	container2 := corev1.Container{
   486  		Name:  "container2",
   487  		Image: "image2",
   488  	}
   489  	initContainer1 := corev1.Container{
   490  		Name:  "initContainer1",
   491  		Image: "image1",
   492  	}
   493  	initContainer2 := corev1.Container{
   494  		Name:  "initContainer2",
   495  		Image: "image2",
   496  	}
   497  
   498  	type args struct {
   499  		configAutomountClient func(ctrl *gomock.Controller) configAutomount.Client
   500  		containers            []corev1.Container
   501  		initContainers        []corev1.Container
   502  	}
   503  	tests := []struct {
   504  		name             string
   505  		args             args
   506  		want             []corev1.Volume
   507  		wantVolumeMounts []corev1.VolumeMount
   508  		wantEnvFroms     []corev1.EnvFromSource
   509  		wantErr          bool
   510  	}{
   511  		{
   512  			name: "No automounting volume",
   513  			args: args{
   514  				configAutomountClient: func(ctrl *gomock.Controller) configAutomount.Client {
   515  					client := configAutomount.NewMockClient(ctrl)
   516  					client.EXPECT().GetAutomountingVolumes().Return([]configAutomount.AutomountInfo{}, nil)
   517  					return client
   518  				},
   519  				containers:     []corev1.Container{container1, container2},
   520  				initContainers: []corev1.Container{initContainer1, initContainer2},
   521  			},
   522  			want:             nil,
   523  			wantVolumeMounts: nil,
   524  			wantErr:          false,
   525  		},
   526  		{
   527  			name: "One PVC",
   528  			args: args{
   529  				configAutomountClient: func(ctrl *gomock.Controller) configAutomount.Client {
   530  					info1 := configAutomount.AutomountInfo{
   531  						VolumeType: configAutomount.VolumeTypePVC,
   532  						VolumeName: "pvc1",
   533  						MountPath:  "/path/to/mount1",
   534  						MountAs:    configAutomount.MountAsFile,
   535  					}
   536  					client := configAutomount.NewMockClient(ctrl)
   537  					client.EXPECT().GetAutomountingVolumes().Return([]configAutomount.AutomountInfo{info1}, nil)
   538  					return client
   539  				},
   540  				containers:     []corev1.Container{container1, container2},
   541  				initContainers: []corev1.Container{initContainer1, initContainer2},
   542  			},
   543  			want: []v1.Volume{
   544  				{
   545  					Name: "auto-pvc-pvc1",
   546  					VolumeSource: v1.VolumeSource{
   547  						PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{
   548  							ClaimName: "pvc1",
   549  						},
   550  					},
   551  				},
   552  			},
   553  			wantVolumeMounts: []v1.VolumeMount{
   554  				{
   555  					Name:      "auto-pvc-pvc1",
   556  					MountPath: "/path/to/mount1",
   557  				},
   558  			},
   559  			wantErr: false,
   560  		},
   561  		{
   562  			name: "One PVC and one secret",
   563  			args: args{
   564  				configAutomountClient: func(ctrl *gomock.Controller) configAutomount.Client {
   565  					info1 := configAutomount.AutomountInfo{
   566  						VolumeType: configAutomount.VolumeTypePVC,
   567  						VolumeName: "pvc1",
   568  						MountPath:  "/path/to/mount1",
   569  						MountAs:    configAutomount.MountAsFile,
   570  					}
   571  					info2 := configAutomount.AutomountInfo{
   572  						VolumeType: configAutomount.VolumeTypeSecret,
   573  						VolumeName: "secret2",
   574  						MountPath:  "/path/to/mount2",
   575  						MountAs:    configAutomount.MountAsFile,
   576  					}
   577  					client := configAutomount.NewMockClient(ctrl)
   578  					client.EXPECT().GetAutomountingVolumes().Return([]configAutomount.AutomountInfo{info1, info2}, nil)
   579  					return client
   580  				},
   581  				containers:     []corev1.Container{container1, container2},
   582  				initContainers: []corev1.Container{initContainer1, initContainer2},
   583  			},
   584  			want: []v1.Volume{
   585  				{
   586  					Name: "auto-pvc-pvc1",
   587  					VolumeSource: v1.VolumeSource{
   588  						PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{
   589  							ClaimName: "pvc1",
   590  						},
   591  					},
   592  				},
   593  				{
   594  					Name: "auto-secret-secret2",
   595  					VolumeSource: v1.VolumeSource{
   596  						Secret: &v1.SecretVolumeSource{
   597  							SecretName: "secret2",
   598  						},
   599  					},
   600  				},
   601  			},
   602  			wantVolumeMounts: []v1.VolumeMount{
   603  				{
   604  					Name:      "auto-pvc-pvc1",
   605  					MountPath: "/path/to/mount1",
   606  				},
   607  				{
   608  					Name:      "auto-secret-secret2",
   609  					MountPath: "/path/to/mount2",
   610  				},
   611  			},
   612  			wantErr: false,
   613  		},
   614  		{
   615  			name: "One PVC, one secret and one configmap",
   616  			args: args{
   617  				configAutomountClient: func(ctrl *gomock.Controller) configAutomount.Client {
   618  					info1 := configAutomount.AutomountInfo{
   619  						VolumeType: configAutomount.VolumeTypePVC,
   620  						VolumeName: "pvc1",
   621  						MountPath:  "/path/to/mount1",
   622  						MountAs:    configAutomount.MountAsFile,
   623  					}
   624  					info2 := configAutomount.AutomountInfo{
   625  						VolumeType: configAutomount.VolumeTypeSecret,
   626  						VolumeName: "secret2",
   627  						MountPath:  "/path/to/mount2",
   628  						MountAs:    configAutomount.MountAsFile,
   629  					}
   630  					info3 := configAutomount.AutomountInfo{
   631  						VolumeType: configAutomount.VolumeTypeConfigmap,
   632  						VolumeName: "cm3",
   633  						MountPath:  "/path/to/mount3",
   634  						MountAs:    configAutomount.MountAsFile,
   635  					}
   636  					client := configAutomount.NewMockClient(ctrl)
   637  					client.EXPECT().GetAutomountingVolumes().Return([]configAutomount.AutomountInfo{info1, info2, info3}, nil)
   638  					return client
   639  				},
   640  				containers:     []corev1.Container{container1, container2},
   641  				initContainers: []corev1.Container{initContainer1, initContainer2},
   642  			},
   643  			want: []v1.Volume{
   644  				{
   645  					Name: "auto-pvc-pvc1",
   646  					VolumeSource: v1.VolumeSource{
   647  						PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{
   648  							ClaimName: "pvc1",
   649  						},
   650  					},
   651  				},
   652  				{
   653  					Name: "auto-secret-secret2",
   654  					VolumeSource: v1.VolumeSource{
   655  						Secret: &v1.SecretVolumeSource{
   656  							SecretName: "secret2",
   657  						},
   658  					},
   659  				},
   660  				{
   661  					Name: "auto-cm-cm3",
   662  					VolumeSource: v1.VolumeSource{
   663  						ConfigMap: &v1.ConfigMapVolumeSource{
   664  							LocalObjectReference: v1.LocalObjectReference{
   665  								Name: "cm3",
   666  							},
   667  						},
   668  					},
   669  				},
   670  			},
   671  			wantVolumeMounts: []v1.VolumeMount{
   672  				{
   673  					Name:      "auto-pvc-pvc1",
   674  					MountPath: "/path/to/mount1",
   675  				},
   676  				{
   677  					Name:      "auto-secret-secret2",
   678  					MountPath: "/path/to/mount2",
   679  				},
   680  				{
   681  					Name:      "auto-cm-cm3",
   682  					MountPath: "/path/to/mount3",
   683  				},
   684  			},
   685  			wantErr: false,
   686  		},
   687  		{
   688  			name: "One secret and one configmap mounted as Env",
   689  			args: args{
   690  				configAutomountClient: func(ctrl *gomock.Controller) configAutomount.Client {
   691  					info1 := configAutomount.AutomountInfo{
   692  						VolumeType: configAutomount.VolumeTypeSecret,
   693  						VolumeName: "secret1",
   694  						MountAs:    configAutomount.MountAsEnv,
   695  					}
   696  					info2 := configAutomount.AutomountInfo{
   697  						VolumeType: configAutomount.VolumeTypeConfigmap,
   698  						VolumeName: "cm2",
   699  						MountAs:    configAutomount.MountAsEnv,
   700  					}
   701  					client := configAutomount.NewMockClient(ctrl)
   702  					client.EXPECT().GetAutomountingVolumes().Return([]configAutomount.AutomountInfo{info1, info2}, nil)
   703  					return client
   704  				},
   705  				containers:     []corev1.Container{container1, container2},
   706  				initContainers: []corev1.Container{initContainer1, initContainer2},
   707  			},
   708  			want:             nil,
   709  			wantVolumeMounts: nil,
   710  			wantEnvFroms: []corev1.EnvFromSource{
   711  				{
   712  					SecretRef: &v1.SecretEnvSource{
   713  						LocalObjectReference: v1.LocalObjectReference{
   714  							Name: "secret1",
   715  						},
   716  					},
   717  				},
   718  				{
   719  					ConfigMapRef: &v1.ConfigMapEnvSource{
   720  						LocalObjectReference: v1.LocalObjectReference{
   721  							Name: "cm2",
   722  						},
   723  					},
   724  				},
   725  			},
   726  			wantErr: false,
   727  		},
   728  		{
   729  			name: "One secret and one configmap mounted as Subpath",
   730  			args: args{
   731  				configAutomountClient: func(ctrl *gomock.Controller) configAutomount.Client {
   732  					info1 := configAutomount.AutomountInfo{
   733  						VolumeType: configAutomount.VolumeTypeSecret,
   734  						VolumeName: "secret1",
   735  						MountPath:  "/path/to/secret1",
   736  						MountAs:    configAutomount.MountAsSubpath,
   737  						Keys:       []string{"secretKey1", "secretKey2"},
   738  					}
   739  					info2 := configAutomount.AutomountInfo{
   740  						VolumeType: configAutomount.VolumeTypeConfigmap,
   741  						VolumeName: "cm2",
   742  						MountPath:  "/path/to/cm2",
   743  						MountAs:    configAutomount.MountAsSubpath,
   744  						Keys:       []string{"cmKey1", "cmKey2"},
   745  					}
   746  					client := configAutomount.NewMockClient(ctrl)
   747  					client.EXPECT().GetAutomountingVolumes().Return([]configAutomount.AutomountInfo{info1, info2}, nil)
   748  					return client
   749  				},
   750  				containers:     []corev1.Container{container1, container2},
   751  				initContainers: []corev1.Container{initContainer1, initContainer2},
   752  			},
   753  			want: []corev1.Volume{
   754  				{
   755  					Name: "auto-secret-secret1",
   756  					VolumeSource: v1.VolumeSource{
   757  						Secret: &v1.SecretVolumeSource{
   758  							SecretName: "secret1",
   759  						},
   760  					},
   761  				},
   762  				{
   763  					Name: "auto-cm-cm2",
   764  					VolumeSource: v1.VolumeSource{
   765  						ConfigMap: &v1.ConfigMapVolumeSource{
   766  							LocalObjectReference: v1.LocalObjectReference{
   767  								Name: "cm2",
   768  							},
   769  						},
   770  					},
   771  				},
   772  			},
   773  			wantVolumeMounts: []corev1.VolumeMount{
   774  				{
   775  					Name:      "auto-secret-secret1",
   776  					MountPath: "/path/to/secret1/secretKey1",
   777  					SubPath:   "secretKey1",
   778  				},
   779  				{
   780  					Name:      "auto-secret-secret1",
   781  					MountPath: "/path/to/secret1/secretKey2",
   782  					SubPath:   "secretKey2",
   783  				},
   784  				{
   785  					Name:      "auto-cm-cm2",
   786  					MountPath: "/path/to/cm2/cmKey1",
   787  					SubPath:   "cmKey1",
   788  				},
   789  				{
   790  					Name:      "auto-cm-cm2",
   791  					MountPath: "/path/to/cm2/cmKey2",
   792  					SubPath:   "cmKey2",
   793  				},
   794  			},
   795  			wantErr: false,
   796  		},
   797  		{
   798  			name: "One secret and one configmap mounted as file with access mode",
   799  			args: args{
   800  				configAutomountClient: func(ctrl *gomock.Controller) configAutomount.Client {
   801  					info1 := configAutomount.AutomountInfo{
   802  						VolumeType:      configAutomount.VolumeTypeSecret,
   803  						VolumeName:      "secret1",
   804  						MountPath:       "/path/to/secret1",
   805  						MountAs:         configAutomount.MountAsFile,
   806  						Keys:            []string{"secretKey1", "secretKey2"},
   807  						MountAccessMode: pointer.Int32(0400),
   808  					}
   809  					info2 := configAutomount.AutomountInfo{
   810  						VolumeType:      configAutomount.VolumeTypeConfigmap,
   811  						VolumeName:      "cm2",
   812  						MountPath:       "/path/to/cm2",
   813  						MountAs:         configAutomount.MountAsFile,
   814  						Keys:            []string{"cmKey1", "cmKey2"},
   815  						MountAccessMode: pointer.Int32(0444),
   816  					}
   817  					client := configAutomount.NewMockClient(ctrl)
   818  					client.EXPECT().GetAutomountingVolumes().Return([]configAutomount.AutomountInfo{info1, info2}, nil)
   819  					return client
   820  				},
   821  				containers:     []corev1.Container{container1, container2},
   822  				initContainers: []corev1.Container{initContainer1, initContainer2},
   823  			},
   824  			want: []corev1.Volume{
   825  				{
   826  					Name: "auto-secret-secret1",
   827  					VolumeSource: v1.VolumeSource{
   828  						Secret: &v1.SecretVolumeSource{
   829  							DefaultMode: pointer.Int32(0400),
   830  							SecretName:  "secret1",
   831  						},
   832  					},
   833  				},
   834  				{
   835  					Name: "auto-cm-cm2",
   836  					VolumeSource: v1.VolumeSource{
   837  						ConfigMap: &v1.ConfigMapVolumeSource{
   838  							DefaultMode: pointer.Int32(0444),
   839  							LocalObjectReference: v1.LocalObjectReference{
   840  								Name: "cm2",
   841  							},
   842  						},
   843  					},
   844  				},
   845  			},
   846  			wantVolumeMounts: []corev1.VolumeMount{
   847  				{
   848  					Name:      "auto-secret-secret1",
   849  					MountPath: "/path/to/secret1",
   850  				},
   851  				{
   852  					Name:      "auto-cm-cm2",
   853  					MountPath: "/path/to/cm2",
   854  				},
   855  			},
   856  			wantErr: false,
   857  		},
   858  		{
   859  			name: "One secret and one configmap mounted as Subpath with access mode",
   860  			args: args{
   861  				configAutomountClient: func(ctrl *gomock.Controller) configAutomount.Client {
   862  					info1 := configAutomount.AutomountInfo{
   863  						VolumeType:      configAutomount.VolumeTypeSecret,
   864  						VolumeName:      "secret1",
   865  						MountPath:       "/path/to/secret1",
   866  						MountAs:         configAutomount.MountAsSubpath,
   867  						Keys:            []string{"secretKey1", "secretKey2"},
   868  						MountAccessMode: pointer.Int32(0400),
   869  					}
   870  					info2 := configAutomount.AutomountInfo{
   871  						VolumeType:      configAutomount.VolumeTypeConfigmap,
   872  						VolumeName:      "cm2",
   873  						MountPath:       "/path/to/cm2",
   874  						MountAs:         configAutomount.MountAsSubpath,
   875  						Keys:            []string{"cmKey1", "cmKey2"},
   876  						MountAccessMode: pointer.Int32(0444),
   877  					}
   878  					client := configAutomount.NewMockClient(ctrl)
   879  					client.EXPECT().GetAutomountingVolumes().Return([]configAutomount.AutomountInfo{info1, info2}, nil)
   880  					return client
   881  				},
   882  				containers:     []corev1.Container{container1, container2},
   883  				initContainers: []corev1.Container{initContainer1, initContainer2},
   884  			},
   885  			want: []corev1.Volume{
   886  				{
   887  					Name: "auto-secret-secret1",
   888  					VolumeSource: v1.VolumeSource{
   889  						Secret: &v1.SecretVolumeSource{
   890  							SecretName:  "secret1",
   891  							DefaultMode: pointer.Int32(0400),
   892  						},
   893  					},
   894  				},
   895  				{
   896  					Name: "auto-cm-cm2",
   897  					VolumeSource: v1.VolumeSource{
   898  						ConfigMap: &v1.ConfigMapVolumeSource{
   899  							LocalObjectReference: v1.LocalObjectReference{
   900  								Name: "cm2",
   901  							},
   902  							DefaultMode: pointer.Int32(0444),
   903  						},
   904  					},
   905  				},
   906  			},
   907  			wantVolumeMounts: []corev1.VolumeMount{
   908  				{
   909  					Name:      "auto-secret-secret1",
   910  					MountPath: "/path/to/secret1/secretKey1",
   911  					SubPath:   "secretKey1",
   912  				},
   913  				{
   914  					Name:      "auto-secret-secret1",
   915  					MountPath: "/path/to/secret1/secretKey2",
   916  					SubPath:   "secretKey2",
   917  				},
   918  				{
   919  					Name:      "auto-cm-cm2",
   920  					MountPath: "/path/to/cm2/cmKey1",
   921  					SubPath:   "cmKey1",
   922  				},
   923  				{
   924  					Name:      "auto-cm-cm2",
   925  					MountPath: "/path/to/cm2/cmKey2",
   926  					SubPath:   "cmKey2",
   927  				},
   928  			},
   929  			wantErr: false,
   930  		},
   931  	}
   932  	for _, tt := range tests {
   933  		t.Run(tt.name, func(t *testing.T) {
   934  			ctrl := gomock.NewController(t)
   935  			got, err := GetAutomountVolumes(tt.args.configAutomountClient(ctrl), tt.args.containers, tt.args.initContainers)
   936  			if (err != nil) != tt.wantErr {
   937  				t.Errorf("GetAutomountVolumes() error = %v, wantErr %v", err, tt.wantErr)
   938  				return
   939  			}
   940  			if diff := cmp.Diff(tt.want, got); diff != "" {
   941  				t.Errorf("GetAutomountVolumes() mismatch (-want +got):\n%s", diff)
   942  			}
   943  
   944  			checkContainers := func(containers, initContainers []corev1.Container) error {
   945  				allContainers := containers
   946  				allContainers = append(allContainers, initContainers...)
   947  				for _, container := range allContainers {
   948  					if diff := cmp.Diff(tt.wantVolumeMounts, container.VolumeMounts); diff != "" {
   949  						return fmt.Errorf(diff)
   950  					}
   951  					if diff := cmp.Diff(tt.wantEnvFroms, container.EnvFrom); diff != "" {
   952  						return fmt.Errorf(diff)
   953  					}
   954  				}
   955  				return nil
   956  			}
   957  
   958  			if err := checkContainers(tt.args.containers, tt.args.initContainers); err != nil {
   959  				t.Errorf("GetAutomountVolumes() containers error: %v", err)
   960  			}
   961  		})
   962  	}
   963  }
   964  

View as plain text