Skip to content

Commit 3d84e61

Browse files
GCSFuse Testing: Cache the gcsfuse version in a config map
1 parent b7181b0 commit 3d84e61

File tree

4 files changed

+133
-3
lines changed

4 files changed

+133
-3
lines changed

pkg/csi_driver/node.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ import (
4040
)
4141

4242
const (
43-
UmountTimeout = time.Second * 5
43+
UmountTimeout = 5 * time.Microsecond
4444
// GCSFuseKernelParamsFilePollInterval is the interval at which the GCSFuse kernel
4545
// parameters file is polled and any changes to kernel parameter files are applied.
4646
GCSFuseKernelParamsFilePollInterval = time.Second * 5

test/e2e/e2e_test.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,20 @@ import (
2525
"strings"
2626
"testing"
2727

28+
apierrors "k8s.io/apimachinery/pkg/api/errors"
2829
"local/test/e2e/specs"
2930
"local/test/e2e/testsuites"
31+
"local/test/e2e/utils"
32+
33+
"context"
34+
35+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
3036

3137
"github.com/googlecloudplatform/gcs-fuse-csi-driver/pkg/cloud_provider/clientset"
3238
"github.com/googlecloudplatform/gcs-fuse-csi-driver/pkg/cloud_provider/metadata"
3339
"github.com/onsi/ginkgo/v2"
3440
"github.com/onsi/gomega"
41+
"k8s.io/client-go/kubernetes"
3542
"k8s.io/client-go/tools/clientcmd"
3643
"k8s.io/klog/v2"
3744
"k8s.io/kubernetes/test/e2e/framework"
@@ -87,8 +94,30 @@ var _ = func() bool {
8794
return true
8895
}()
8996

97+
func maybeDeleteGCSFuseVersionConfigMap() {
98+
config, err := clientcmd.BuildConfigFromFlags("", framework.TestContext.KubeConfig)
99+
if err != nil {
100+
klog.Errorf("Failed to build kube config while deleting gcsfuse version configmap: %v", err)
101+
return
102+
}
103+
104+
standardClient, err := kubernetes.NewForConfig(config)
105+
if err != nil {
106+
klog.Errorf("Failed to create client while deleting gcsfuse version configmap: %v", err)
107+
return
108+
}
109+
err = standardClient.CoreV1().ConfigMaps(utils.DefaultNamespace).Delete(context.Background(), specs.GcsfuseVersionConfigMapName, metav1.DeleteOptions{})
110+
if err != nil && !apierrors.IsNotFound(err) {
111+
klog.Errorf("Failed to delete gcsfuse version configmap: %v", err)
112+
}
113+
}
114+
90115
func TestE2E(t *testing.T) {
116+
// Try to delete the gcsfuse version configmap before running the tests. This is to handle the case where the previous test run is interrupted and the configmap is not deleted, which can cause issues for the current test run.
117+
maybeDeleteGCSFuseVersionConfigMap()
91118
t.Parallel()
119+
// Delete the gcsfuse version configmap after the test finishes.
120+
defer maybeDeleteGCSFuseVersionConfigMap()
92121
gomega.RegisterFailHandler(framework.Fail)
93122
if framework.TestContext.ReportDir != "" {
94123
if err := os.MkdirAll(framework.TestContext.ReportDir, 0o755); err != nil {

test/e2e/specs/specs.go

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ import (
3838
"k8s.io/apimachinery/pkg/fields"
3939
"k8s.io/apimachinery/pkg/util/version"
4040
"k8s.io/apimachinery/pkg/util/wait"
41+
"k8s.io/klog/v2"
4142

4243
clientset "k8s.io/client-go/kubernetes"
4344
"k8s.io/kubernetes/pkg/kubelet/events"
@@ -118,6 +119,9 @@ const (
118119
driverDaemonsetLabel = "k8s-app=gcs-fuse-csi-driver"
119120

120121
IsOSSEnvVar = "IS_OSS"
122+
123+
GcsfuseVersionConfigMapName = "gcsfuse-version-config"
124+
gcsfuseVersionConfigMapKey = "gcsfuse-version"
121125
)
122126

123127
// Note to developers adding new testing methods - Please check the code path of newly added methods and ensure that those requiring
@@ -1073,6 +1077,15 @@ func (t *TestJob) Cleanup(ctx context.Context) {
10731077
}
10741078

10751079
func GetGCSFuseVersion(ctx context.Context, f *framework.Framework) string {
1080+
versionData, err := utils.ReadConfigMap(ctx, f.ClientSet, utils.DefaultNamespace, GcsfuseVersionConfigMapName)
1081+
if err != nil {
1082+
klog.Errorf("Failed to read GCS Fuse version configmap %s: %v, will retrieve it manually", GcsfuseVersionConfigMapName, err)
1083+
}
1084+
1085+
if versionData != nil && versionData[gcsfuseVersionConfigMapKey] != "" {
1086+
return versionData[gcsfuseVersionConfigMapKey]
1087+
}
1088+
10761089
client := f.ClientSet
10771090
configMaps, err := client.CoreV1().ConfigMaps("").List(ctx, metav1.ListOptions{
10781091
FieldSelector: "metadata.name=gcsfusecsi-image-config",
@@ -1121,7 +1134,14 @@ func GetGCSFuseVersion(ctx context.Context, f *framework.Framework) string {
11211134
// Versioning package (https://semver.org/#spec-item-9) treats `-gke.V` as pre release packages which can lead to comparison erros like v3.1.0 > v3.1.0-gke.0 (not considered same)
11221135
framework.Logf("Received GCS Fuse version %s does not follow to x.y.z-gke.v format which might lead to unprecedented test skips, continuing with %s", l[2])
11231136
}
1124-
return l[2]
1137+
gcsfuseVersion := l[2]
1138+
err = utils.UpsertConfigMap(ctx, f.ClientSet, utils.DefaultNamespace, GcsfuseVersionConfigMapName, map[string]string{
1139+
gcsfuseVersionConfigMapKey: gcsfuseVersion,
1140+
})
1141+
if err != nil {
1142+
klog.Errorf("Failed to upsert GCS Fuse version %s to configmap %s: %v, continuing...", gcsfuseVersion, GcsfuseVersionConfigMapName, err)
1143+
}
1144+
return gcsfuseVersion
11251145
}
11261146

11271147
func GCSFuseVersionAndBranch(ctx context.Context, f *framework.Framework) (*version.Version, string) {

test/e2e/utils/utils.go

Lines changed: 82 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,23 +18,39 @@ limitations under the License.
1818
package utils
1919

2020
import (
21+
"context"
2122
"fmt"
2223
"os"
2324
"os/exec"
2425
"strings"
26+
"time"
2527

28+
corev1 "k8s.io/api/core/v1"
29+
apierrors "k8s.io/apimachinery/pkg/api/errors"
30+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2631
"k8s.io/apimachinery/pkg/util/version"
32+
"k8s.io/apimachinery/pkg/util/wait"
33+
"k8s.io/client-go/kubernetes"
2734
"k8s.io/klog/v2"
2835
)
2936

30-
const MinGCSFuseKernelParamsVersion = "v3.7.0-gke.0"
37+
const (
38+
DefaultNamespace = "default"
39+
MinGCSFuseKernelParamsVersion = "v3.7.0-gke.0"
40+
)
3141

3242
var (
3343
MasterBranchName = "master"
3444

3545
// Use release branch for corresponding gcsfuse version. This ensures we
3646
// can pick up test fixes without requiring a new gcsfuse release.
3747
gcsfuseReleaseBranchFormat = "v%v.%v.%v_release"
48+
configMapBackoff = wait.Backoff{
49+
Duration: 200 * time.Millisecond,
50+
Factor: 2.0,
51+
Jitter: 0.1,
52+
Steps: 5,
53+
}
3854
)
3955

4056
func EnsureVariable(v *string, set bool, msgOnError string) {
@@ -76,3 +92,68 @@ func GCSFuseBranch(gcsfuseVersionStr string) (*version.Version, string) {
7692

7793
return v, fmt.Sprintf(gcsfuseReleaseBranchFormat, v.Major(), v.Minor(), v.Patch())
7894
}
95+
96+
func ReadConfigMap(
97+
ctx context.Context,
98+
client kubernetes.Interface,
99+
namespace, name string,
100+
) (map[string]string, error) {
101+
102+
cm, err := client.CoreV1().
103+
ConfigMaps(namespace).
104+
Get(ctx, name, metav1.GetOptions{})
105+
106+
if err != nil {
107+
return nil, err
108+
}
109+
110+
return cm.Data, nil
111+
}
112+
113+
func UpsertConfigMap(
114+
ctx context.Context,
115+
client kubernetes.Interface,
116+
namespace, name string,
117+
data map[string]string,
118+
) error {
119+
120+
cmClient := client.CoreV1().ConfigMaps(namespace)
121+
122+
// First try create
123+
_, err := cmClient.Create(ctx, &corev1.ConfigMap{
124+
ObjectMeta: metav1.ObjectMeta{
125+
Name: name,
126+
},
127+
Data: data,
128+
}, metav1.CreateOptions{})
129+
130+
if err == nil {
131+
return nil
132+
}
133+
134+
if !apierrors.IsAlreadyExists(err) {
135+
return err
136+
}
137+
138+
// Exists → update with retry on conflict
139+
return wait.ExponentialBackoffWithContext(ctx, configMapBackoff, func(ctx context.Context) (bool, error) {
140+
existing, err := cmClient.Get(ctx, name, metav1.GetOptions{})
141+
if err != nil {
142+
return false, err
143+
}
144+
145+
if existing.Data == nil {
146+
existing.Data = make(map[string]string)
147+
}
148+
for k, v := range data {
149+
existing.Data[k] = v
150+
}
151+
152+
_, err = cmClient.Update(ctx, existing, metav1.UpdateOptions{})
153+
if apierrors.IsConflict(err) {
154+
return false, nil
155+
}
156+
157+
return true, err
158+
})
159+
}

0 commit comments

Comments
 (0)