Skip to content

Commit 3a78641

Browse files
committed
fix fakeClientset for unit tests + add e2e tests
1 parent 6d0f66b commit 3a78641

7 files changed

Lines changed: 91 additions & 21 deletions

File tree

pkg/cloud_provider/clientset/fake.go

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,19 @@ package clientset
1919

2020
import (
2121
"context"
22+
"strconv"
2223

2324
"github.com/googlecloudplatform/gcs-fuse-csi-driver/pkg/webhook"
2425
authenticationv1 "k8s.io/api/authentication/v1"
2526
corev1 "k8s.io/api/core/v1"
2627
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2728
)
2829

30+
type FakeNodeConfig struct {
31+
IsWorkloadIdentityEnabled bool
32+
MachineType string
33+
}
34+
2935
type FakeClientset struct {
3036
fakePod *corev1.Pod
3137
fakeNode *corev1.Node
@@ -35,7 +41,7 @@ func NewFakeClientset() *FakeClientset {
3541
fakeClientSet := &FakeClientset{}
3642
// Default setting for most unit tests is pod doesn't use host network & workload identity is enabled on the node
3743
fakeClientSet.CreatePod( /*hostNetworkEnabled */ false)
38-
fakeClientSet.CreateNode( /* isWorkloadIdentityEnabledOnNode */ true)
44+
fakeClientSet.CreateNode(FakeNodeConfig{IsWorkloadIdentityEnabled: true})
3945

4046
return fakeClientSet
4147
}
@@ -74,16 +80,18 @@ func (c *FakeClientset) CreatePod(hostNetworkEnabled bool) {
7480
}
7581
}
7682

77-
func (c *FakeClientset) CreateNode(isWorkloadIdentityEnabled bool) {
83+
func (c *FakeClientset) CreateNode(nodeConfig FakeNodeConfig) {
7884
c.fakeNode = &corev1.Node{
7985
ObjectMeta: metav1.ObjectMeta{
8086
Name: "",
8187
Labels: map[string]string{},
8288
},
8389
}
8490

85-
if isWorkloadIdentityEnabled {
86-
c.fakeNode.Labels[GkeMetaDataServerKey] = "true"
91+
c.fakeNode.Labels[GkeMetaDataServerKey] = strconv.FormatBool(nodeConfig.IsWorkloadIdentityEnabled)
92+
c.fakeNode.Labels[MachineTypeKey] = nodeConfig.MachineType
93+
if c.fakeNode.Labels[MachineTypeKey] == "" {
94+
c.fakeNode.Labels[MachineTypeKey] = "e2-medium"
8795
}
8896
}
8997

pkg/csi_driver/node.go

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -183,15 +183,16 @@ func (s *nodeServer) NodePublishVolume(ctx context.Context, req *csi.NodePublish
183183
}
184184
}
185185

186-
machineType, ok := node.Labels[clientset.MachineTypeKey]
187186
shouldDisableAutoConfig := s.driver.config.DisableAutoconfig
188-
189-
flagMap := map[string]string{"machine-type": machineType, "disable-autoconfig": strconv.FormatBool(shouldDisableAutoConfig)}
190-
187+
machineType, ok := node.Labels[clientset.MachineTypeKey]
188+
// TODO: Add check for whether sidecar is managed and >= minimum version with compatible gcsfuse
191189
if ok {
190+
flagMap := map[string]string{"machine-type": machineType, "disable-autoconfig": strconv.FormatBool(shouldDisableAutoConfig)}
192191
if err := PutFlagsFromDriverToTargetPath(flagMap, targetPath, FlagFileForDefaultingPath); err != nil {
193192
return nil, status.Error(codes.Internal, err.Error())
194193
}
194+
} else {
195+
klog.Warningf("Unable to fetch node %v's machine type", node.Name)
195196
}
196197

197198
// Check if there is any error from the gcsfuse

pkg/csi_driver/node_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -247,7 +247,7 @@ func TestNodePublishVolumeWIDisabledOnNode(t *testing.T) {
247247
}
248248
for _, test := range cases {
249249
fakeClientSet := &clientset.FakeClientset{}
250-
fakeClientSet.CreateNode( /* workloadIdentityEnabled */ test.workloadIdentityEnabledOnNode)
250+
fakeClientSet.CreateNode( /* workloadIdentityEnabled */ clientset.FakeNodeConfig{IsWorkloadIdentityEnabled: test.workloadIdentityEnabledOnNode})
251251
fakeClientSet.CreatePod( /* hostNetworkEnabled */ test.hostNetworkEnabledOnPod)
252252
testEnv := initTestNodeServerWithCustomClientset(t, fakeClientSet)
253253

pkg/csi_driver/utils.go

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -474,20 +474,22 @@ func getSidecarContainerStatus(isInitContainer bool, pod *corev1.Pod) (*corev1.C
474474
}
475475

476476
func isSidecarVersionSupportedForTokenServer(imageName string) bool {
477+
return isSidecarVersionSupportedForGivenFeature(imageName, tokenServerSidecarMinVersion)
478+
}
479+
480+
func isSidecarVersionSupportedForGivenFeature(imageName string, sidecarMinSupportedVersion string) bool {
477481
managedSidecarPattern := `.*/gke-release(-staging)?/gcs-fuse-csi-driver-sidecar-mounter:v\d+.\d+.\d+-gke\.\d+.*`
478482
re := regexp.MustCompile(managedSidecarPattern)
479483
isManagedSidecar := re.MatchString(imageName)
480484

481485
if !isManagedSidecar {
482486
klog.Infof("mountOptions should not be passed because this is a private sidecar image %q", imageName)
483-
484487
return false
485488
}
486489
imageVersion := strings.Split(strings.Split(imageName, ":")[1], "@")[0]
487490
klog.Infof("sidecar image version: %v", imageVersion)
488-
if semver.Compare(imageVersion, tokenServerSidecarMinVersion) >= 0 {
491+
if semver.Compare(imageVersion, sidecarMinSupportedVersion) >= 0 {
489492
klog.Infof("sidecar version is supported for token server")
490-
491493
return true
492494
}
493495

@@ -505,20 +507,15 @@ func PutFlagsFromDriverToTargetPath(flagMap map[string]string, targetPath string
505507

506508
f, err := os.Create(absolutePath)
507509
if err != nil {
508-
return fmt.Errorf("failed to create defaulting flag file: %w", err)
510+
return fmt.Errorf("failed to create defaulting-flag file: %w", err)
509511
}
510512
content := prepareFileContentFromFlagMap(flagMap)
511513
if _, err := f.WriteString(content); err != nil {
512-
return fmt.Errorf("failed to write defaulting flag file: %w", err)
514+
return fmt.Errorf("failed to write defaulting-flag file: %w", err)
513515
}
514516

515517
f.Close()
516518

517-
err = os.Chown(absolutePath, webhook.NobodyUID, webhook.NobodyGID)
518-
if err != nil {
519-
return fmt.Errorf("failed to change ownership on the machine-type file: %w", err)
520-
}
521-
522519
return nil
523520
}
524521

test/e2e/specs/specs.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,8 @@ const (
8686
ReadAheadCustomReadAheadKb = "15360"
8787
ReadAheadCustomMaxRatio = "100"
8888

89+
DisableAutoconfig = "disable-autoconfig"
90+
8991
GoogleCloudCliImage = "gcr.io/google.com/cloudsdktool/google-cloud-cli:slim"
9092
GolangImage = "golang:1.22.7"
9193
UbuntuImage = "ubuntu:20.04"
@@ -406,6 +408,15 @@ func (t *TestPod) GetNode() string {
406408
return t.pod.Spec.NodeName
407409
}
408410

411+
func (t *TestPod) GetMachineType(ctx context.Context) (string, error) {
412+
nodeName := t.GetNode()
413+
node, err := t.client.CoreV1().Nodes().Get(ctx, nodeName, metav1.GetOptions{})
414+
if err != nil {
415+
return "", fmt.Errorf("error getting test node %v's machine type ", nodeName)
416+
}
417+
return node.ObjectMeta.Labels["node.kubernetes.io/instance-type"], nil
418+
}
419+
409420
func (t *TestPod) GetCSIDriverNodePodIP(ctx context.Context) string {
410421
node := t.GetNode()
411422
daemonSetLabelSelector := "k8s-app=gcs-fuse-csi-driver"
@@ -1237,3 +1248,18 @@ func DeployIstioSidecar(namespace string) {
12371248
func DeployIstioServiceEntry(namespace string) {
12381249
e2ekubectl.RunKubectlOrDie(namespace, "apply", "--filename", "./specs/istio-service-entry.yaml")
12391250
}
1251+
1252+
func (t *TestPod) VerifyDefaultingFlagsArePassed(namespace string, expectedMachineTypeFlag string, expectedDisableAutoconfigFlag bool) {
1253+
stdout, stderr, err := e2ekubectl.RunKubectlWithFullOutput(namespace, "logs", t.pod.Name, "-c", "gke-gcsfuse-sidecar")
1254+
framework.ExpectNoError(err,
1255+
"Error accessing logs from pod %v, but failed with error message %q\nstdout: %s\nstderr: %s",
1256+
t.pod.Name, err, stdout, stderr)
1257+
1258+
expectedDisableAutoconfigFlagString := fmt.Sprintf(`"DisableAutoconfig":%t`, expectedDisableAutoconfigFlag)
1259+
expectedMachineTypeFlagString := fmt.Sprintf(`"MachineType":"%s"`, expectedMachineTypeFlag)
1260+
1261+
gomega.Expect(stdout).To(gomega.ContainSubstring(expectedDisableAutoconfigFlagString),
1262+
"Should find DisableAutoconfig flag string %q in stdout:\n%s", expectedDisableAutoconfigFlagString, stdout)
1263+
gomega.Expect(stdout).To(gomega.ContainSubstring(expectedMachineTypeFlagString),
1264+
"Should find MachineType flag string %q in stdout:\n%s", expectedMachineTypeFlagString, stdout)
1265+
}

test/e2e/specs/testdriver.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,8 @@ func (n *GCSFuseCSITestDriver) CreateVolume(ctx context.Context, config *storage
239239
case EnableMetadataPrefetchAndInvalidMountOptionsVolumePrefix:
240240
mountOptions += ",file-system:kernel-list-cache-ttl-secs:-1,invalid-option"
241241
v.metadataPrefetch = true
242+
case DisableAutoconfig:
243+
mountOptions += ",disable-autoconfig"
242244
}
243245

244246
v.mountOptions = mountOptions

test/e2e/testsuites/mount.go

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,12 @@ import (
2121
"context"
2222
"fmt"
2323
"os"
24+
"slices"
2425
"strconv"
2526

27+
"local/test/e2e/specs"
28+
"local/test/e2e/utils"
29+
2630
"github.com/googlecloudplatform/gcs-fuse-csi-driver/pkg/webhook"
2731
"github.com/onsi/ginkgo/v2"
2832
"github.com/onsi/gomega"
@@ -33,8 +37,6 @@ import (
3337
e2evolume "k8s.io/kubernetes/test/e2e/framework/volume"
3438
storageframework "k8s.io/kubernetes/test/e2e/storage/framework"
3539
admissionapi "k8s.io/pod-security-admission/api"
36-
"local/test/e2e/specs"
37-
"local/test/e2e/utils"
3840
)
3941

4042
type gcsFuseCSIMountTestSuite struct {
@@ -183,6 +185,40 @@ func (t *gcsFuseCSIMountTestSuite) DefineTests(driver storageframework.TestDrive
183185
tPod.Cleanup(ctx)
184186
}
185187

188+
testDefaultingFlags := func(configPrefix ...string) {
189+
init(configPrefix...)
190+
defer cleanup()
191+
192+
ginkgo.By("Configuring test pod")
193+
tPod := specs.NewTestPod(f.ClientSet, f.Namespace)
194+
tPod.SetupVolume(l.volumeResource, volumeName, mountPath, false)
195+
196+
tPod.Create(ctx)
197+
198+
ginkgo.By("Checking pod is running")
199+
tPod.WaitForRunning(ctx)
200+
201+
machineType, err := tPod.GetMachineType(ctx)
202+
framework.ExpectNoError(err, "error getting node's machine type")
203+
204+
if slices.Contains(configPrefix, specs.DisableAutoconfig) {
205+
tPod.VerifyDefaultingFlagsArePassed(f.Namespace.Name, machineType /* disableAutoconfig */, true)
206+
} else {
207+
tPod.VerifyDefaultingFlagsArePassed(f.Namespace.Name, machineType /* disableAutoconfig */, false)
208+
}
209+
210+
ginkgo.By("Deleting pod")
211+
tPod.Cleanup(ctx)
212+
}
213+
214+
ginkgo.It("should pass --machine-type and --disable-autoconfig=false (default driver flag) to gcsfuse ", func() {
215+
testDefaultingFlags()
216+
})
217+
218+
ginkgo.It("should pass --machine-type and --disable-autoconfig=true (overwritten as part of mountOptions) to gcsfuse", func() {
219+
testDefaultingFlags(specs.DisableAutoconfig)
220+
})
221+
186222
ginkgo.It("[read ahead config] should update read ahead config knobs", func() {
187223
if pattern.VolType == storageframework.DynamicPV {
188224
e2eskipper.Skipf("skip for volume type %v", storageframework.DynamicPV)

0 commit comments

Comments
 (0)