...

Source file src/k8s.io/kubernetes/pkg/volume/configmap/configmap_test.go

Documentation: k8s.io/kubernetes/pkg/volume/configmap

     1  /*
     2  Copyright 2015 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package configmap
    18  
    19  import (
    20  	"fmt"
    21  	"io/ioutil"
    22  	"os"
    23  	"path/filepath"
    24  	"reflect"
    25  	"strings"
    26  	"testing"
    27  
    28  	"k8s.io/api/core/v1"
    29  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    30  	"k8s.io/apimachinery/pkg/types"
    31  	clientset "k8s.io/client-go/kubernetes"
    32  	"k8s.io/client-go/kubernetes/fake"
    33  	"k8s.io/kubernetes/pkg/volume"
    34  	"k8s.io/kubernetes/pkg/volume/emptydir"
    35  	volumetest "k8s.io/kubernetes/pkg/volume/testing"
    36  	"k8s.io/kubernetes/pkg/volume/util"
    37  )
    38  
    39  func TestMakePayload(t *testing.T) {
    40  	caseMappingMode := int32(0400)
    41  	cases := []struct {
    42  		name      string
    43  		mappings  []v1.KeyToPath
    44  		configMap *v1.ConfigMap
    45  		mode      int32
    46  		optional  bool
    47  		payload   map[string]util.FileProjection
    48  		success   bool
    49  	}{
    50  		{
    51  			name: "no overrides",
    52  			configMap: &v1.ConfigMap{
    53  				Data: map[string]string{
    54  					"foo": "foo",
    55  					"bar": "bar",
    56  				},
    57  			},
    58  			mode: 0644,
    59  			payload: map[string]util.FileProjection{
    60  				"foo": {Data: []byte("foo"), Mode: 0644},
    61  				"bar": {Data: []byte("bar"), Mode: 0644},
    62  			},
    63  			success: true,
    64  		},
    65  		{
    66  			name: "no overrides binary data",
    67  			configMap: &v1.ConfigMap{
    68  				BinaryData: map[string][]byte{
    69  					"foo": []byte("foo"),
    70  					"bar": []byte("bar"),
    71  				},
    72  			},
    73  			mode: 0644,
    74  			payload: map[string]util.FileProjection{
    75  				"foo": {Data: []byte("foo"), Mode: 0644},
    76  				"bar": {Data: []byte("bar"), Mode: 0644},
    77  			},
    78  			success: true,
    79  		},
    80  		{
    81  			name: "no overrides mixed data",
    82  			configMap: &v1.ConfigMap{
    83  				BinaryData: map[string][]byte{
    84  					"foo": []byte("foo"),
    85  				},
    86  				Data: map[string]string{
    87  					"bar": "bar",
    88  				},
    89  			},
    90  			mode: 0644,
    91  			payload: map[string]util.FileProjection{
    92  				"foo": {Data: []byte("foo"), Mode: 0644},
    93  				"bar": {Data: []byte("bar"), Mode: 0644},
    94  			},
    95  			success: true,
    96  		},
    97  		{
    98  			name: "basic 1",
    99  			mappings: []v1.KeyToPath{
   100  				{
   101  					Key:  "foo",
   102  					Path: "path/to/foo.txt",
   103  				},
   104  			},
   105  			configMap: &v1.ConfigMap{
   106  				Data: map[string]string{
   107  					"foo": "foo",
   108  					"bar": "bar",
   109  				},
   110  			},
   111  			mode: 0644,
   112  			payload: map[string]util.FileProjection{
   113  				"path/to/foo.txt": {Data: []byte("foo"), Mode: 0644},
   114  			},
   115  			success: true,
   116  		},
   117  		{
   118  			name: "subdirs",
   119  			mappings: []v1.KeyToPath{
   120  				{
   121  					Key:  "foo",
   122  					Path: "path/to/1/2/3/foo.txt",
   123  				},
   124  			},
   125  			configMap: &v1.ConfigMap{
   126  				Data: map[string]string{
   127  					"foo": "foo",
   128  					"bar": "bar",
   129  				},
   130  			},
   131  			mode: 0644,
   132  			payload: map[string]util.FileProjection{
   133  				"path/to/1/2/3/foo.txt": {Data: []byte("foo"), Mode: 0644},
   134  			},
   135  			success: true,
   136  		},
   137  		{
   138  			name: "subdirs 2",
   139  			mappings: []v1.KeyToPath{
   140  				{
   141  					Key:  "foo",
   142  					Path: "path/to/1/2/3/foo.txt",
   143  				},
   144  			},
   145  			configMap: &v1.ConfigMap{
   146  				Data: map[string]string{
   147  					"foo": "foo",
   148  					"bar": "bar",
   149  				},
   150  			},
   151  			mode: 0644,
   152  			payload: map[string]util.FileProjection{
   153  				"path/to/1/2/3/foo.txt": {Data: []byte("foo"), Mode: 0644},
   154  			},
   155  			success: true,
   156  		},
   157  		{
   158  			name: "subdirs 3",
   159  			mappings: []v1.KeyToPath{
   160  				{
   161  					Key:  "foo",
   162  					Path: "path/to/1/2/3/foo.txt",
   163  				},
   164  				{
   165  					Key:  "bar",
   166  					Path: "another/path/to/the/esteemed/bar.bin",
   167  				},
   168  			},
   169  			configMap: &v1.ConfigMap{
   170  				Data: map[string]string{
   171  					"foo": "foo",
   172  					"bar": "bar",
   173  				},
   174  			},
   175  			mode: 0644,
   176  			payload: map[string]util.FileProjection{
   177  				"path/to/1/2/3/foo.txt":                {Data: []byte("foo"), Mode: 0644},
   178  				"another/path/to/the/esteemed/bar.bin": {Data: []byte("bar"), Mode: 0644},
   179  			},
   180  			success: true,
   181  		},
   182  		{
   183  			name: "non existent key",
   184  			mappings: []v1.KeyToPath{
   185  				{
   186  					Key:  "zab",
   187  					Path: "path/to/foo.txt",
   188  				},
   189  			},
   190  			configMap: &v1.ConfigMap{
   191  				Data: map[string]string{
   192  					"foo": "foo",
   193  					"bar": "bar",
   194  				},
   195  			},
   196  			mode:    0644,
   197  			success: false,
   198  		},
   199  		{
   200  			name: "mapping with Mode",
   201  			mappings: []v1.KeyToPath{
   202  				{
   203  					Key:  "foo",
   204  					Path: "foo.txt",
   205  					Mode: &caseMappingMode,
   206  				},
   207  				{
   208  					Key:  "bar",
   209  					Path: "bar.bin",
   210  					Mode: &caseMappingMode,
   211  				},
   212  			},
   213  			configMap: &v1.ConfigMap{
   214  				Data: map[string]string{
   215  					"foo": "foo",
   216  					"bar": "bar",
   217  				},
   218  			},
   219  			mode: 0644,
   220  			payload: map[string]util.FileProjection{
   221  				"foo.txt": {Data: []byte("foo"), Mode: caseMappingMode},
   222  				"bar.bin": {Data: []byte("bar"), Mode: caseMappingMode},
   223  			},
   224  			success: true,
   225  		},
   226  		{
   227  			name: "mapping with defaultMode",
   228  			mappings: []v1.KeyToPath{
   229  				{
   230  					Key:  "foo",
   231  					Path: "foo.txt",
   232  				},
   233  				{
   234  					Key:  "bar",
   235  					Path: "bar.bin",
   236  				},
   237  			},
   238  			configMap: &v1.ConfigMap{
   239  				Data: map[string]string{
   240  					"foo": "foo",
   241  					"bar": "bar",
   242  				},
   243  			},
   244  			mode: 0644,
   245  			payload: map[string]util.FileProjection{
   246  				"foo.txt": {Data: []byte("foo"), Mode: 0644},
   247  				"bar.bin": {Data: []byte("bar"), Mode: 0644},
   248  			},
   249  			success: true,
   250  		},
   251  		{
   252  			name: "optional non existent key",
   253  			mappings: []v1.KeyToPath{
   254  				{
   255  					Key:  "zab",
   256  					Path: "path/to/foo.txt",
   257  				},
   258  			},
   259  			configMap: &v1.ConfigMap{
   260  				Data: map[string]string{
   261  					"foo": "foo",
   262  					"bar": "bar",
   263  				},
   264  			},
   265  			mode:     0644,
   266  			optional: true,
   267  			payload:  map[string]util.FileProjection{},
   268  			success:  true,
   269  		},
   270  	}
   271  
   272  	for _, tc := range cases {
   273  		actualPayload, err := MakePayload(tc.mappings, tc.configMap, &tc.mode, tc.optional)
   274  		if err != nil && tc.success {
   275  			t.Errorf("%v: unexpected failure making payload: %v", tc.name, err)
   276  			continue
   277  		}
   278  
   279  		if err == nil && !tc.success {
   280  			t.Errorf("%v: unexpected success making payload", tc.name)
   281  			continue
   282  		}
   283  
   284  		if !tc.success {
   285  			continue
   286  		}
   287  
   288  		if e, a := tc.payload, actualPayload; !reflect.DeepEqual(e, a) {
   289  			t.Errorf("%v: expected and actual payload do not match", tc.name)
   290  		}
   291  	}
   292  }
   293  
   294  func newTestHost(t *testing.T, clientset clientset.Interface) (string, volume.VolumeHost) {
   295  	tempDir, err := ioutil.TempDir("", "configmap_volume_test.")
   296  	if err != nil {
   297  		t.Fatalf("can't make a temp rootdir: %v", err)
   298  	}
   299  
   300  	return tempDir, volumetest.NewFakeVolumeHost(t, tempDir, clientset, emptydir.ProbeVolumePlugins())
   301  }
   302  
   303  func TestCanSupport(t *testing.T) {
   304  	pluginMgr := volume.VolumePluginMgr{}
   305  	tempDir, host := newTestHost(t, nil)
   306  	defer os.RemoveAll(tempDir)
   307  	pluginMgr.InitPlugins(ProbeVolumePlugins(), nil /* prober */, host)
   308  
   309  	plugin, err := pluginMgr.FindPluginByName(configMapPluginName)
   310  	if err != nil {
   311  		t.Fatal("Can't find the plugin by name")
   312  	}
   313  	if plugin.GetPluginName() != configMapPluginName {
   314  		t.Errorf("Wrong name: %s", plugin.GetPluginName())
   315  	}
   316  	if !plugin.CanSupport(&volume.Spec{Volume: &v1.Volume{VolumeSource: v1.VolumeSource{ConfigMap: &v1.ConfigMapVolumeSource{LocalObjectReference: v1.LocalObjectReference{Name: ""}}}}}) {
   317  		t.Errorf("Expected true")
   318  	}
   319  	if plugin.CanSupport(&volume.Spec{}) {
   320  		t.Errorf("Expected false")
   321  	}
   322  }
   323  
   324  func TestPlugin(t *testing.T) {
   325  	var (
   326  		testPodUID     = types.UID("test_pod_uid")
   327  		testVolumeName = "test_volume_name"
   328  		testNamespace  = "test_configmap_namespace"
   329  		testName       = "test_configmap_name"
   330  
   331  		volumeSpec    = volumeSpec(testVolumeName, testName, 0644)
   332  		configMap     = configMap(testNamespace, testName)
   333  		client        = fake.NewSimpleClientset(&configMap)
   334  		pluginMgr     = volume.VolumePluginMgr{}
   335  		tempDir, host = newTestHost(t, client)
   336  	)
   337  
   338  	defer os.RemoveAll(tempDir)
   339  	pluginMgr.InitPlugins(ProbeVolumePlugins(), nil /* prober */, host)
   340  
   341  	plugin, err := pluginMgr.FindPluginByName(configMapPluginName)
   342  	if err != nil {
   343  		t.Fatal("Can't find the plugin by name")
   344  	}
   345  
   346  	pod := &v1.Pod{ObjectMeta: metav1.ObjectMeta{Namespace: testNamespace, UID: testPodUID}}
   347  	mounter, err := plugin.NewMounter(volume.NewSpecFromVolume(volumeSpec), pod, volume.VolumeOptions{})
   348  	if err != nil {
   349  		t.Errorf("Failed to make a new Mounter: %v", err)
   350  	}
   351  	if mounter == nil {
   352  		t.Fatalf("Got a nil Mounter")
   353  	}
   354  
   355  	vName, err := plugin.GetVolumeName(volume.NewSpecFromVolume(volumeSpec))
   356  	if err != nil {
   357  		t.Errorf("Failed to GetVolumeName: %v", err)
   358  	}
   359  	if vName != "test_volume_name/test_configmap_name" {
   360  		t.Errorf("Got unexpected VolumeName %v", vName)
   361  	}
   362  
   363  	volumePath := mounter.GetPath()
   364  	if !hasPathSuffix(volumePath, "pods/test_pod_uid/volumes/kubernetes.io~configmap/test_volume_name") {
   365  		t.Errorf("Got unexpected path: %s", volumePath)
   366  	}
   367  
   368  	var mounterArgs volume.MounterArgs
   369  	group := int64(1001)
   370  	mounterArgs.FsGroup = &group
   371  	err = mounter.SetUp(mounterArgs)
   372  	if err != nil {
   373  		t.Errorf("Failed to setup volume: %v", err)
   374  	}
   375  	if _, err := os.Stat(volumePath); err != nil {
   376  		if os.IsNotExist(err) {
   377  			t.Errorf("SetUp() failed, volume path not created: %s", volumePath)
   378  		} else {
   379  			t.Errorf("SetUp() failed: %v", err)
   380  		}
   381  	}
   382  
   383  	doTestConfigMapDataInVolume(volumePath, configMap, t)
   384  	doTestCleanAndTeardown(plugin, testPodUID, testVolumeName, volumePath, t)
   385  }
   386  
   387  // Test the case where the plugin's ready file exists, but the volume dir is not a
   388  // mountpoint, which is the state the system will be in after reboot.  The dir
   389  // should be mounter and the configMap data written to it.
   390  func TestPluginReboot(t *testing.T) {
   391  	var (
   392  		testPodUID     = types.UID("test_pod_uid3")
   393  		testVolumeName = "test_volume_name"
   394  		testNamespace  = "test_configmap_namespace"
   395  		testName       = "test_configmap_name"
   396  
   397  		volumeSpec    = volumeSpec(testVolumeName, testName, 0644)
   398  		configMap     = configMap(testNamespace, testName)
   399  		client        = fake.NewSimpleClientset(&configMap)
   400  		pluginMgr     = volume.VolumePluginMgr{}
   401  		rootDir, host = newTestHost(t, client)
   402  	)
   403  
   404  	defer os.RemoveAll(rootDir)
   405  	pluginMgr.InitPlugins(ProbeVolumePlugins(), nil /* prober */, host)
   406  
   407  	plugin, err := pluginMgr.FindPluginByName(configMapPluginName)
   408  	if err != nil {
   409  		t.Fatal("Can't find the plugin by name")
   410  	}
   411  
   412  	pod := &v1.Pod{ObjectMeta: metav1.ObjectMeta{Namespace: testNamespace, UID: testPodUID}}
   413  	mounter, err := plugin.NewMounter(volume.NewSpecFromVolume(volumeSpec), pod, volume.VolumeOptions{})
   414  	if err != nil {
   415  		t.Errorf("Failed to make a new Mounter: %v", err)
   416  	}
   417  	if mounter == nil {
   418  		t.Fatalf("Got a nil Mounter")
   419  	}
   420  
   421  	podMetadataDir := fmt.Sprintf("%v/pods/test_pod_uid3/plugins/kubernetes.io~configmap/test_volume_name", rootDir)
   422  	util.SetReady(podMetadataDir)
   423  	volumePath := mounter.GetPath()
   424  	if !hasPathSuffix(volumePath, "pods/test_pod_uid3/volumes/kubernetes.io~configmap/test_volume_name") {
   425  		t.Errorf("Got unexpected path: %s", volumePath)
   426  	}
   427  
   428  	var mounterArgs volume.MounterArgs
   429  	group := int64(1001)
   430  	mounterArgs.FsGroup = &group
   431  	err = mounter.SetUp(mounterArgs)
   432  	if err != nil {
   433  		t.Errorf("Failed to setup volume: %v", err)
   434  	}
   435  	if _, err := os.Stat(volumePath); err != nil {
   436  		if os.IsNotExist(err) {
   437  			t.Errorf("SetUp() failed, volume path not created: %s", volumePath)
   438  		} else {
   439  			t.Errorf("SetUp() failed: %v", err)
   440  		}
   441  	}
   442  
   443  	doTestConfigMapDataInVolume(volumePath, configMap, t)
   444  	doTestCleanAndTeardown(plugin, testPodUID, testVolumeName, volumePath, t)
   445  }
   446  
   447  func TestPluginOptional(t *testing.T) {
   448  	var (
   449  		testPodUID     = types.UID("test_pod_uid")
   450  		testVolumeName = "test_volume_name"
   451  		testNamespace  = "test_configmap_namespace"
   452  		testName       = "test_configmap_name"
   453  		trueVal        = true
   454  
   455  		volumeSpec    = volumeSpec(testVolumeName, testName, 0644)
   456  		client        = fake.NewSimpleClientset()
   457  		pluginMgr     = volume.VolumePluginMgr{}
   458  		tempDir, host = newTestHost(t, client)
   459  	)
   460  	volumeSpec.VolumeSource.ConfigMap.Optional = &trueVal
   461  
   462  	defer os.RemoveAll(tempDir)
   463  	pluginMgr.InitPlugins(ProbeVolumePlugins(), nil /* prober */, host)
   464  
   465  	plugin, err := pluginMgr.FindPluginByName(configMapPluginName)
   466  	if err != nil {
   467  		t.Fatal("Can't find the plugin by name")
   468  	}
   469  
   470  	pod := &v1.Pod{ObjectMeta: metav1.ObjectMeta{Namespace: testNamespace, UID: testPodUID}}
   471  	mounter, err := plugin.NewMounter(volume.NewSpecFromVolume(volumeSpec), pod, volume.VolumeOptions{})
   472  	if err != nil {
   473  		t.Errorf("Failed to make a new Mounter: %v", err)
   474  	}
   475  	if mounter == nil {
   476  		t.Errorf("Got a nil Mounter")
   477  	}
   478  
   479  	vName, err := plugin.GetVolumeName(volume.NewSpecFromVolume(volumeSpec))
   480  	if err != nil {
   481  		t.Errorf("Failed to GetVolumeName: %v", err)
   482  	}
   483  	if vName != "test_volume_name/test_configmap_name" {
   484  		t.Errorf("Got unexpected VolumeName %v", vName)
   485  	}
   486  
   487  	volumePath := mounter.GetPath()
   488  	if !hasPathSuffix(volumePath, "pods/test_pod_uid/volumes/kubernetes.io~configmap/test_volume_name") {
   489  		t.Errorf("Got unexpected path: %s", volumePath)
   490  	}
   491  
   492  	var mounterArgs volume.MounterArgs
   493  	group := int64(1001)
   494  	mounterArgs.FsGroup = &group
   495  	err = mounter.SetUp(mounterArgs)
   496  	if err != nil {
   497  		t.Errorf("Failed to setup volume: %v", err)
   498  	}
   499  	if _, err := os.Stat(volumePath); err != nil {
   500  		if os.IsNotExist(err) {
   501  			t.Errorf("SetUp() failed, volume path not created: %s", volumePath)
   502  		} else {
   503  			t.Errorf("SetUp() failed: %v", err)
   504  		}
   505  	}
   506  
   507  	datadirSymlink := filepath.Join(volumePath, "..data")
   508  	datadir, err := os.Readlink(datadirSymlink)
   509  	if err != nil && os.IsNotExist(err) {
   510  		t.Fatalf("couldn't find volume path's data dir, %s", datadirSymlink)
   511  	} else if err != nil {
   512  		t.Fatalf("couldn't read symlink, %s", datadirSymlink)
   513  	}
   514  	datadirPath := filepath.Join(volumePath, datadir)
   515  
   516  	infos, err := ioutil.ReadDir(volumePath)
   517  	if err != nil {
   518  		t.Fatalf("couldn't find volume path, %s", volumePath)
   519  	}
   520  	if len(infos) != 0 {
   521  		for _, fi := range infos {
   522  			if fi.Name() != "..data" && fi.Name() != datadir {
   523  				t.Errorf("empty data directory, %s, is not empty. Contains: %s", datadirSymlink, fi.Name())
   524  			}
   525  		}
   526  	}
   527  
   528  	infos, err = ioutil.ReadDir(datadirPath)
   529  	if err != nil {
   530  		t.Fatalf("couldn't find volume data path, %s", datadirPath)
   531  	}
   532  	if len(infos) != 0 {
   533  		t.Errorf("empty data directory, %s, is not empty. Contains: %s", datadirSymlink, infos[0].Name())
   534  	}
   535  
   536  	doTestCleanAndTeardown(plugin, testPodUID, testVolumeName, volumePath, t)
   537  }
   538  
   539  func TestPluginKeysOptional(t *testing.T) {
   540  	var (
   541  		testPodUID     = types.UID("test_pod_uid")
   542  		testVolumeName = "test_volume_name"
   543  		testNamespace  = "test_configmap_namespace"
   544  		testName       = "test_configmap_name"
   545  		trueVal        = true
   546  
   547  		volumeSpec    = volumeSpec(testVolumeName, testName, 0644)
   548  		configMap     = configMap(testNamespace, testName)
   549  		client        = fake.NewSimpleClientset(&configMap)
   550  		pluginMgr     = volume.VolumePluginMgr{}
   551  		tempDir, host = newTestHost(t, client)
   552  	)
   553  	volumeSpec.VolumeSource.ConfigMap.Items = []v1.KeyToPath{
   554  		{Key: "data-1", Path: "data-1"},
   555  		{Key: "data-2", Path: "data-2"},
   556  		{Key: "data-3", Path: "data-3"},
   557  		{Key: "missing", Path: "missing"},
   558  	}
   559  	volumeSpec.VolumeSource.ConfigMap.Optional = &trueVal
   560  
   561  	defer os.RemoveAll(tempDir)
   562  	pluginMgr.InitPlugins(ProbeVolumePlugins(), nil /* prober */, host)
   563  
   564  	plugin, err := pluginMgr.FindPluginByName(configMapPluginName)
   565  	if err != nil {
   566  		t.Fatal("Can't find the plugin by name")
   567  	}
   568  
   569  	pod := &v1.Pod{ObjectMeta: metav1.ObjectMeta{Namespace: testNamespace, UID: testPodUID}}
   570  	mounter, err := plugin.NewMounter(volume.NewSpecFromVolume(volumeSpec), pod, volume.VolumeOptions{})
   571  	if err != nil {
   572  		t.Errorf("Failed to make a new Mounter: %v", err)
   573  	}
   574  	if mounter == nil {
   575  		t.Errorf("Got a nil Mounter")
   576  	}
   577  
   578  	vName, err := plugin.GetVolumeName(volume.NewSpecFromVolume(volumeSpec))
   579  	if err != nil {
   580  		t.Errorf("Failed to GetVolumeName: %v", err)
   581  	}
   582  	if vName != "test_volume_name/test_configmap_name" {
   583  		t.Errorf("Got unexpected VolumeName %v", vName)
   584  	}
   585  
   586  	volumePath := mounter.GetPath()
   587  	if !hasPathSuffix(volumePath, "pods/test_pod_uid/volumes/kubernetes.io~configmap/test_volume_name") {
   588  		t.Errorf("Got unexpected path: %s", volumePath)
   589  	}
   590  
   591  	var mounterArgs volume.MounterArgs
   592  	group := int64(1001)
   593  	mounterArgs.FsGroup = &group
   594  	err = mounter.SetUp(mounterArgs)
   595  	if err != nil {
   596  		t.Errorf("Failed to setup volume: %v", err)
   597  	}
   598  	if _, err := os.Stat(volumePath); err != nil {
   599  		if os.IsNotExist(err) {
   600  			t.Errorf("SetUp() failed, volume path not created: %s", volumePath)
   601  		} else {
   602  			t.Errorf("SetUp() failed: %v", err)
   603  		}
   604  	}
   605  
   606  	doTestConfigMapDataInVolume(volumePath, configMap, t)
   607  	doTestCleanAndTeardown(plugin, testPodUID, testVolumeName, volumePath, t)
   608  }
   609  
   610  func volumeSpec(volumeName, configMapName string, defaultMode int32) *v1.Volume {
   611  	return &v1.Volume{
   612  		Name: volumeName,
   613  		VolumeSource: v1.VolumeSource{
   614  			ConfigMap: &v1.ConfigMapVolumeSource{
   615  				LocalObjectReference: v1.LocalObjectReference{
   616  					Name: configMapName,
   617  				},
   618  				DefaultMode: &defaultMode,
   619  			},
   620  		},
   621  	}
   622  }
   623  
   624  func TestInvalidConfigMapSetup(t *testing.T) {
   625  	var (
   626  		testPodUID     = types.UID("test_pod_uid")
   627  		testVolumeName = "test_volume_name"
   628  		testNamespace  = "test_configmap_namespace"
   629  		testName       = "test_configmap_name"
   630  
   631  		volumeSpec    = volumeSpec(testVolumeName, testName, 0644)
   632  		configMap     = configMap(testNamespace, testName)
   633  		client        = fake.NewSimpleClientset(&configMap)
   634  		pluginMgr     = volume.VolumePluginMgr{}
   635  		tempDir, host = newTestHost(t, client)
   636  	)
   637  	volumeSpec.VolumeSource.ConfigMap.Items = []v1.KeyToPath{
   638  		{Key: "missing", Path: "missing"},
   639  	}
   640  
   641  	defer os.RemoveAll(tempDir)
   642  	pluginMgr.InitPlugins(ProbeVolumePlugins(), nil /* prober */, host)
   643  
   644  	plugin, err := pluginMgr.FindPluginByName(configMapPluginName)
   645  	if err != nil {
   646  		t.Fatal("Can't find the plugin by name")
   647  	}
   648  
   649  	pod := &v1.Pod{ObjectMeta: metav1.ObjectMeta{Namespace: testNamespace, UID: testPodUID}}
   650  	mounter, err := plugin.NewMounter(volume.NewSpecFromVolume(volumeSpec), pod, volume.VolumeOptions{})
   651  	if err != nil {
   652  		t.Errorf("Failed to make a new Mounter: %v", err)
   653  	}
   654  	if mounter == nil {
   655  		t.Errorf("Got a nil Mounter")
   656  	}
   657  
   658  	vName, err := plugin.GetVolumeName(volume.NewSpecFromVolume(volumeSpec))
   659  	if err != nil {
   660  		t.Errorf("Failed to GetVolumeName: %v", err)
   661  	}
   662  	if vName != "test_volume_name/test_configmap_name" {
   663  		t.Errorf("Got unexpected VolumeName %v", vName)
   664  	}
   665  
   666  	volumePath := mounter.GetPath()
   667  	if !hasPathSuffix(volumePath, "pods/test_pod_uid/volumes/kubernetes.io~configmap/test_volume_name") {
   668  		t.Errorf("Got unexpected path: %s", volumePath)
   669  	}
   670  
   671  	var mounterArgs volume.MounterArgs
   672  	group := int64(1001)
   673  	mounterArgs.FsGroup = &group
   674  	err = mounter.SetUp(mounterArgs)
   675  	if err == nil {
   676  		t.Errorf("Expected setup to fail")
   677  	}
   678  	_, err = os.Stat(volumePath)
   679  	if err == nil {
   680  		t.Errorf("Expected %s to not exist", volumePath)
   681  	}
   682  
   683  	doTestCleanAndTeardown(plugin, testPodUID, testVolumeName, volumePath, t)
   684  }
   685  
   686  func configMap(namespace, name string) v1.ConfigMap {
   687  	return v1.ConfigMap{
   688  		ObjectMeta: metav1.ObjectMeta{
   689  			Namespace: namespace,
   690  			Name:      name,
   691  		},
   692  		Data: map[string]string{
   693  			"data-1": "value-1",
   694  			"data-2": "value-2",
   695  			"data-3": "value-3",
   696  		},
   697  	}
   698  }
   699  
   700  func doTestConfigMapDataInVolume(volumePath string, configMap v1.ConfigMap, t *testing.T) {
   701  	for key, value := range configMap.Data {
   702  		configMapDataHostPath := filepath.Join(volumePath, key)
   703  		if _, err := os.Stat(configMapDataHostPath); err != nil {
   704  			t.Fatalf("SetUp() failed, couldn't find configMap data on disk: %v", configMapDataHostPath)
   705  		} else {
   706  			actualValue, err := ioutil.ReadFile(configMapDataHostPath)
   707  			if err != nil {
   708  				t.Fatalf("Couldn't read configMap data from: %v", configMapDataHostPath)
   709  			}
   710  
   711  			if value != string(actualValue) {
   712  				t.Errorf("Unexpected value; expected %q, got %q", value, actualValue)
   713  			}
   714  		}
   715  	}
   716  }
   717  
   718  func doTestCleanAndTeardown(plugin volume.VolumePlugin, podUID types.UID, testVolumeName, volumePath string, t *testing.T) {
   719  	unmounter, err := plugin.NewUnmounter(testVolumeName, podUID)
   720  	if err != nil {
   721  		t.Errorf("Failed to make a new Unmounter: %v", err)
   722  	}
   723  	if unmounter == nil {
   724  		t.Fatalf("Got a nil Unmounter")
   725  	}
   726  
   727  	if err := unmounter.TearDown(); err != nil {
   728  		t.Errorf("Expected success, got: %v", err)
   729  	}
   730  	if _, err := os.Stat(volumePath); err == nil {
   731  		t.Errorf("TearDown() failed, volume path still exists: %s", volumePath)
   732  	} else if !os.IsNotExist(err) {
   733  		t.Errorf("TearDown() failed: %v", err)
   734  	}
   735  }
   736  
   737  func hasPathSuffix(s, suffix string) bool {
   738  	return strings.HasSuffix(s, filepath.FromSlash(suffix))
   739  }
   740  

View as plain text