@@ -137,6 +137,24 @@ func kernelParamValueFromConfigFile(f *framework.Framework, tPod *specs.TestPod,
137137 return ""
138138}
139139
140+ func updateKernelParamValueInConfigFileAtomically (f * framework.Framework , tPod * specs.TestPod , paramName ParamName , volumeName , newValue string ) {
141+ configFilePath := kernelParamsConfigFilePath (volumeName )
142+ originalContent := tPod .VerifyExecInPodSucceedWithOutput (f , specs .TesterContainerName , fmt .Sprintf ("cat %s" , configFilePath ))
143+
144+ // Using a regular expression to replace the value of the specified parameter.
145+ // This approach is chosen to be resilient to formatting changes in the JSON file.
146+ re := regexp .MustCompile (fmt .Sprintf (`("name"\s*:\s*"%s".*?"value"\s*:\s*")[^"]*(")` , regexp .QuoteMeta (string (paramName ))))
147+ newContent := re .ReplaceAllString (originalContent , fmt .Sprintf ("${1}%s${2}" , newValue ))
148+
149+ tmpConfigFile := fmt .Sprintf ("%s-tmp" , configFilePath )
150+ // Write the updated content to a temporary file in the pod.
151+ // Using a heredoc to avoid issues with special characters in the content.
152+ tPod .VerifyExecInPodSucceed (f , specs .TesterContainerName , fmt .Sprintf ("cat <<'EOF' > %s\n %s\n EOF" , tmpConfigFile , newContent ))
153+
154+ // Atomically move the temporary file to the original file path.
155+ tPod .VerifyExecInPodSucceed (f , specs .TesterContainerName , fmt .Sprintf ("mv %s %s" , tmpConfigFile , configFilePath ))
156+ }
157+
140158func KernelParamValueFromMount (f * framework.Framework , tPod * specs.TestPod , paramName ParamName ) string {
141159 bdi := tPod .VerifyExecInPodSucceedWithOutput (f , specs .TesterContainerName , fmt .Sprintf (`mountpoint -d "%s"` , mountPath ))
142160 parts := strings .Split (strings .TrimSpace (bdi ), ":" )
@@ -271,7 +289,7 @@ func (t *gcsFuseCSIKernelParamsTestSuite) DefineTests(driver storageframework.Te
271289 tPod .Cleanup (ctx )
272290 })
273291
274- ginkgo .It ("should verify that max-background and congestion-threshold are changed to GCSFuse user provided value for zonal bucket" , func () {
292+ ginkgo .It ("should verify that max-background and congestion-threshold are changed to user provided value for zonal bucket" , func () {
275293 if driver , ok := driver .(* specs.GCSFuseCSITestDriver ); ok && ! driver .EnableZB {
276294 e2eskipper .Skipf ("skip for regional bucket" )
277295 }
@@ -281,14 +299,14 @@ func (t *gcsFuseCSIKernelParamsTestSuite) DefineTests(driver storageframework.Te
281299 ginkgo .By ("Configuring and setting up test pod" )
282300 tPod := setupAndDeployTestPod (ctx , f , l .volumeResource , true /* needsFuseConnections */ , fmt .Sprintf ("file-system:max-background:%s,file-system:congestion-threshold:%s" , CustomMaxBackground , CustomCongestionThreshold ))
283301
284- ginkgo .By ("Verifying max-background is eventually changed to GCSFuse default value" )
302+ ginkgo .By ("Verifying max-background is eventually changed to user provided value" )
285303 expectedMaxBackground := kernelParamValueFromConfigFile (f , tPod , volumeName , MaxBackgroundRequests )
286304 gomega .Expect (CustomMaxBackground ).Should (gomega .Equal (expectedMaxBackground ))
287305 gomega .Eventually (func () string {
288306 return KernelParamValueFromMount (f , tPod , MaxBackgroundRequests )
289307 }, retryTimeout , retryPolling ).Should (gomega .Equal (expectedMaxBackground ))
290308
291- ginkgo .By ("Verifying congestion-threshold is eventually changed to GCSFuse default value" )
309+ ginkgo .By ("Verifying congestion-threshold is eventually changed to user provided value" )
292310 expectedCongestionThreshold := kernelParamValueFromConfigFile (f , tPod , volumeName , CongestionWindowThreshold )
293311 gomega .Expect (CustomCongestionThreshold ).Should (gomega .Equal (expectedCongestionThreshold ))
294312 gomega .Eventually (func () string {
@@ -299,6 +317,37 @@ func (t *gcsFuseCSIKernelParamsTestSuite) DefineTests(driver storageframework.Te
299317 tPod .Cleanup (ctx )
300318 })
301319
320+ ginkgo .DescribeTable ("should verify that kernel params are continuously updated if config file is changed for zonal bucket" ,
321+ func (paramName ParamName , newValue string , needsFuseConnections bool ) {
322+ if driver , ok := driver .(* specs.GCSFuseCSITestDriver ); ok && ! driver .EnableZB {
323+ e2eskipper .Skipf ("skip for regional bucket" )
324+ }
325+ init (specs .EnableKernelParamsPrefix )
326+ defer cleanup ()
327+
328+ ginkgo .By ("Configuring and setting up test pod" )
329+ tPod := setupAndDeployTestPod (ctx , f , l .volumeResource , true /* needsFuseConnections */ )
330+
331+ ginkgo .By (fmt .Sprintf ("Verifying %s is eventually changed to GCSFuse default value" , paramName ))
332+ expectedDefaultValue := kernelParamValueFromConfigFile (f , tPod , volumeName , paramName )
333+ gomega .Eventually (func () string {
334+ return KernelParamValueFromMount (f , tPod , paramName )
335+ }, retryTimeout , retryPolling ).Should (gomega .Equal (expectedDefaultValue ))
336+
337+ ginkgo .By (fmt .Sprintf ("Verifying %s is eventually changed to new value upon config file change" , paramName ))
338+ updateKernelParamValueInConfigFileAtomically (f , tPod , paramName , volumeName , newValue )
339+ gomega .Eventually (func () string {
340+ return KernelParamValueFromMount (f , tPod , paramName )
341+ }, retryTimeout , retryPolling ).Should (gomega .Equal (newValue ))
342+
343+ ginkgo .By ("Deleting the pod" )
344+ tPod .Cleanup (ctx )
345+ },
346+ ginkgo .Entry ("for read-ahead-kb" , MaxReadAheadKb , CustomGCSFuseMaxReadAhead8MB , false ),
347+ ginkgo .Entry ("for max-background" , MaxBackgroundRequests , CustomMaxBackground , true ),
348+ ginkgo .Entry ("for congestion-threshold" , CongestionWindowThreshold , CustomCongestionThreshold , true ),
349+ )
350+
302351 ginkgo .It ("should verify kernel params config file is not written for regional bucket" , func () {
303352 if driver , ok := driver .(* specs.GCSFuseCSITestDriver ); ok && driver .EnableZB {
304353 e2eskipper .Skipf ("skip for zonal bucket" )
0 commit comments