...

Source file src/k8s.io/kubernetes/pkg/volume/csi/csi_util_test.go

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

     1  /*
     2  Copyright 2019 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 csi
    18  
    19  import (
    20  	"bytes"
    21  	"encoding/json"
    22  	"flag"
    23  	"fmt"
    24  	"os"
    25  	"path/filepath"
    26  	"testing"
    27  	"time"
    28  
    29  	api "k8s.io/api/core/v1"
    30  	storagev1 "k8s.io/api/storage/v1"
    31  	"k8s.io/apimachinery/pkg/api/resource"
    32  	meta "k8s.io/apimachinery/pkg/apis/meta/v1"
    33  	"k8s.io/klog/v2"
    34  	"k8s.io/kubernetes/pkg/volume"
    35  )
    36  
    37  // TestMain starting point for all tests.
    38  // Surfaces klog flags by default to enable
    39  // go test -v ./ --args <klog flags>
    40  func TestMain(m *testing.M) {
    41  	klog.InitFlags(flag.CommandLine)
    42  	os.Exit(m.Run())
    43  }
    44  
    45  func makeTestPVWithMountOptions(name string, sizeGig int, driverName, volID string, mountOptions []string) *api.PersistentVolume {
    46  	pv := makeTestPV(name, sizeGig, driverName, volID)
    47  	pv.Spec.MountOptions = mountOptions
    48  	return pv
    49  }
    50  
    51  func makeTestPV(name string, sizeGig int, driverName, volID string) *api.PersistentVolume {
    52  	return &api.PersistentVolume{
    53  		ObjectMeta: meta.ObjectMeta{
    54  			Name: name,
    55  		},
    56  		Spec: api.PersistentVolumeSpec{
    57  			AccessModes: []api.PersistentVolumeAccessMode{api.ReadWriteOnce},
    58  			Capacity: api.ResourceList{
    59  				api.ResourceName(api.ResourceStorage): resource.MustParse(
    60  					fmt.Sprintf("%dGi", sizeGig),
    61  				),
    62  			},
    63  			PersistentVolumeSource: api.PersistentVolumeSource{
    64  				CSI: &api.CSIPersistentVolumeSource{
    65  					Driver:       driverName,
    66  					VolumeHandle: volID,
    67  					ReadOnly:     false,
    68  				},
    69  			},
    70  		},
    71  	}
    72  }
    73  
    74  func makeTestVol(name string, driverName string) *api.Volume {
    75  	ro := false
    76  	return &api.Volume{
    77  		Name: name,
    78  		VolumeSource: api.VolumeSource{
    79  			CSI: &api.CSIVolumeSource{
    80  				Driver:   driverName,
    81  				ReadOnly: &ro,
    82  			},
    83  		},
    84  	}
    85  }
    86  
    87  func getTestCSIDriver(name string, podInfoMount *bool, attachable *bool, volumeLifecycleModes []storagev1.VolumeLifecycleMode) *storagev1.CSIDriver {
    88  	defaultFSGroupPolicy := storagev1.ReadWriteOnceWithFSTypeFSGroupPolicy
    89  	seLinuxMountSupport := true
    90  	noSElinuxMountSupport := false
    91  	driver := &storagev1.CSIDriver{
    92  		ObjectMeta: meta.ObjectMeta{
    93  			Name: name,
    94  		},
    95  		Spec: storagev1.CSIDriverSpec{
    96  			PodInfoOnMount:       podInfoMount,
    97  			AttachRequired:       attachable,
    98  			VolumeLifecycleModes: volumeLifecycleModes,
    99  			FSGroupPolicy:        &defaultFSGroupPolicy,
   100  		},
   101  	}
   102  	switch driver.Name {
   103  	case "supports_selinux":
   104  		driver.Spec.SELinuxMount = &seLinuxMountSupport
   105  	case "no_selinux":
   106  		driver.Spec.SELinuxMount = &noSElinuxMountSupport
   107  	}
   108  	return driver
   109  }
   110  
   111  func TestSaveVolumeData(t *testing.T) {
   112  	plug, tmpDir := newTestPlugin(t, nil)
   113  	defer os.RemoveAll(tmpDir)
   114  	testCases := []struct {
   115  		name       string
   116  		data       map[string]string
   117  		shouldFail bool
   118  	}{
   119  		{name: "test with data ok", data: map[string]string{"key0": "val0", "_key1": "val1", "key2": "val2"}},
   120  		{name: "test with data ok 2 ", data: map[string]string{"_key0_": "val0", "&key1": "val1", "key2": "val2"}},
   121  	}
   122  
   123  	for i, tc := range testCases {
   124  		t.Logf("test case: %s", tc.name)
   125  		specVolID := fmt.Sprintf("spec-volid-%d", i)
   126  		targetPath := getTargetPath(testPodUID, specVolID, plug.host)
   127  		mountDir := filepath.Join(targetPath, "mount")
   128  		if err := os.MkdirAll(mountDir, 0755); err != nil && !os.IsNotExist(err) {
   129  			t.Errorf("failed to create dir [%s]: %v", mountDir, err)
   130  		}
   131  
   132  		err := saveVolumeData(targetPath, volDataFileName, tc.data)
   133  
   134  		if !tc.shouldFail && err != nil {
   135  			t.Errorf("unexpected failure: %v", err)
   136  		}
   137  		// did file get created
   138  		dataDir := getTargetPath(testPodUID, specVolID, plug.host)
   139  		file := filepath.Join(dataDir, volDataFileName)
   140  		if _, err := os.Stat(file); err != nil {
   141  			t.Errorf("failed to create data dir: %v", err)
   142  		}
   143  
   144  		// validate content
   145  		data, err := os.ReadFile(file)
   146  		if !tc.shouldFail && err != nil {
   147  			t.Errorf("failed to read data file: %v", err)
   148  		}
   149  
   150  		jsonData := new(bytes.Buffer)
   151  		if err := json.NewEncoder(jsonData).Encode(tc.data); err != nil {
   152  			t.Errorf("failed to encode json: %v", err)
   153  		}
   154  		if string(data) != jsonData.String() {
   155  			t.Errorf("expecting encoded data %v, got %v", string(data), jsonData)
   156  		}
   157  	}
   158  }
   159  
   160  func TestCreateCSIOperationContext(t *testing.T) {
   161  	testCases := []struct {
   162  		name     string
   163  		spec     *volume.Spec
   164  		migrated string
   165  	}{
   166  		{
   167  			name:     "test volume spec nil",
   168  			spec:     nil,
   169  			migrated: "false",
   170  		},
   171  		{
   172  			name: "test volume normal spec with migrated true",
   173  			spec: &volume.Spec{
   174  				Migrated: true,
   175  			},
   176  			migrated: "true",
   177  		},
   178  		{
   179  			name: "test volume normal spec with migrated false",
   180  			spec: &volume.Spec{
   181  				Migrated: false,
   182  			},
   183  			migrated: "false",
   184  		},
   185  	}
   186  	for _, tc := range testCases {
   187  		t.Logf("test case: %s", tc.name)
   188  		timeout := time.Minute
   189  		ctx, _ := createCSIOperationContext(tc.spec, timeout)
   190  
   191  		additionalInfoVal := ctx.Value(additionalInfoKey)
   192  		if additionalInfoVal == nil {
   193  			t.Error("Could not load additional info from context")
   194  		}
   195  		additionalInfoV, ok := additionalInfoVal.(additionalInfo)
   196  		if !ok {
   197  			t.Errorf("Additional info type assertion fail, additionalInfo object: %v", additionalInfoVal)
   198  		}
   199  		migrated := additionalInfoV.Migrated
   200  		if migrated != tc.migrated {
   201  			t.Errorf("Expect migrated value: %v, got: %v", tc.migrated, migrated)
   202  		}
   203  	}
   204  }
   205  

View as plain text