From 64903eb166a9d6125da20f3dc0b37e7c61477837 Mon Sep 17 00:00:00 2001 From: John Gardiner Myers Date: Thu, 5 Jan 2023 17:48:12 -0800 Subject: [PATCH 1/2] Hold reference to VFSContext from Factory --- cmd/kops/create.go | 5 +++-- cmd/kops/delete.go | 3 +-- cmd/kops/replace.go | 5 +++-- cmd/kops/util/factory.go | 11 ++++++++++- cmd/kops/version.go | 3 +-- 5 files changed, 18 insertions(+), 9 deletions(-) diff --git a/cmd/kops/create.go b/cmd/kops/create.go index 51c31a7480..9b57604a22 100644 --- a/cmd/kops/create.go +++ b/cmd/kops/create.go @@ -33,7 +33,6 @@ import ( "k8s.io/kops/pkg/kubemanifest" "k8s.io/kops/upup/pkg/fi/cloudup" "k8s.io/kops/util/pkg/text" - "k8s.io/kops/util/pkg/vfs" "k8s.io/kubectl/pkg/util/i18n" "k8s.io/kubectl/pkg/util/templates" ) @@ -102,6 +101,8 @@ func RunCreate(ctx context.Context, f *util.Factory, out io.Writer, c *CreateOpt return err } + vfsContext := f.VFSContext() + clusterName := "" // var cSpec = false var sb bytes.Buffer @@ -118,7 +119,7 @@ func RunCreate(ctx context.Context, f *util.Factory, out io.Writer, c *CreateOpt return err } } else { - contents, err = vfs.Context.ReadFile(f) + contents, err = vfsContext.ReadFile(f) if err != nil { return fmt.Errorf("error reading file %q: %v", f, err) } diff --git a/cmd/kops/delete.go b/cmd/kops/delete.go index f34c146336..bce5a08ab2 100644 --- a/cmd/kops/delete.go +++ b/cmd/kops/delete.go @@ -28,7 +28,6 @@ import ( kopsapi "k8s.io/kops/pkg/apis/kops" "k8s.io/kops/pkg/kopscodecs" "k8s.io/kops/util/pkg/text" - "k8s.io/kops/util/pkg/vfs" "k8s.io/kubectl/pkg/util/i18n" "k8s.io/kubectl/pkg/util/templates" ) @@ -91,7 +90,7 @@ func RunDelete(ctx context.Context, factory *util.Factory, out io.Writer, d *Del return fmt.Errorf("reading from stdin: %v", err) } } else { - contents, err = vfs.Context.ReadFile(f) + contents, err = factory.VFSContext().ReadFile(f) if err != nil { return fmt.Errorf("reading file %q: %v", f, err) } diff --git a/cmd/kops/replace.go b/cmd/kops/replace.go index c902ca228b..dedb007d61 100644 --- a/cmd/kops/replace.go +++ b/cmd/kops/replace.go @@ -30,7 +30,6 @@ import ( "k8s.io/kops/pkg/kopscodecs" "k8s.io/kops/upup/pkg/fi/cloudup" "k8s.io/kops/util/pkg/text" - "k8s.io/kops/util/pkg/vfs" "k8s.io/kubectl/pkg/util/i18n" "k8s.io/kubectl/pkg/util/templates" ) @@ -90,6 +89,8 @@ func RunReplace(ctx context.Context, f *util.Factory, out io.Writer, c *ReplaceO return err } + vfsContext := f.VFSContext() + for _, f := range c.Filenames { var contents []byte if f == "-" { @@ -98,7 +99,7 @@ func RunReplace(ctx context.Context, f *util.Factory, out io.Writer, c *ReplaceO return err } } else { - contents, err = vfs.Context.ReadFile(f) + contents, err = vfsContext.ReadFile(f) if err != nil { return fmt.Errorf("error reading file %q: %v", f, err) } diff --git a/cmd/kops/util/factory.go b/cmd/kops/util/factory.go index 90fdaf0124..c2df485834 100644 --- a/cmd/kops/util/factory.go +++ b/cmd/kops/util/factory.go @@ -51,6 +51,7 @@ type Factory struct { kubernetesClient kubernetes.Interface certManagerClient certmanager.Interface + vfsContext *vfs.VFSContext cachedRESTConfig *rest.Config dynamicClient dynamic.Interface @@ -119,7 +120,7 @@ func (f *Factory) KopsClient() (simple.Clientset, error) { KopsClient: kopsClient.Kops(), } } else { - basePath, err := vfs.Context.BuildVfsPath(registryPath) + basePath, err := f.VFSContext().BuildVfsPath(registryPath) if err != nil { return nil, fmt.Errorf("error building path for %q: %v", registryPath, err) } @@ -221,3 +222,11 @@ func (f *Factory) RESTMapper() (*restmapper.DeferredDiscoveryRESTMapper, error) return f.restMapper, nil } + +func (f *Factory) VFSContext() *vfs.VFSContext { + if f.vfsContext == nil { + // TODO vfs.NewVFSContext() + f.vfsContext = vfs.Context + } + return f.vfsContext +} diff --git a/cmd/kops/version.go b/cmd/kops/version.go index 175d28a297..4af1ea5cff 100644 --- a/cmd/kops/version.go +++ b/cmd/kops/version.go @@ -25,7 +25,6 @@ import ( "k8s.io/kops" "k8s.io/kops/cmd/kops/util" "k8s.io/kops/pkg/apis/kops/registry" - "k8s.io/kops/util/pkg/vfs" "k8s.io/kubectl/pkg/util/i18n" "k8s.io/kubectl/pkg/util/templates" ) @@ -116,7 +115,7 @@ func serverVersion(f *util.Factory, options *VersionOptions) string { if err != nil { return "could not fetch cluster" } - configBase, err := vfs.Context.BuildVfsPath(cluster.Spec.ConfigBase) + configBase, err := f.VFSContext().BuildVfsPath(cluster.Spec.ConfigBase) if err != nil { return "could not talk to vfs" } From 11304807f28cfb97a775b8fcf1b1321550710044 Mon Sep 17 00:00:00 2001 From: John Gardiner Myers Date: Fri, 6 Jan 2023 23:01:51 -0800 Subject: [PATCH 2/2] Hold reference to VFSContext from simple.Clientset --- cmd/kops/util/factory.go | 11 +++---- examples/kops-api-example/apply.go | 3 +- examples/kops-api-example/up.go | 3 +- nodeup/pkg/model/kubelet_test.go | 2 +- pkg/client/simple/api/clientset.go | 17 +++++++++-- pkg/client/simple/clientset.go | 3 ++ pkg/client/simple/vfsclientset/clientset.go | 30 +++++++++++-------- .../simple/vfsclientset/clientset_test.go | 10 +++++-- pkg/instancegroups/rollingupdate_os_test.go | 2 +- upup/pkg/fi/cloudup/apply_cluster.go | 2 +- .../cloudup/bootstrapchannelbuilder_test.go | 2 +- upup/pkg/fi/cloudup/new_cluster.go | 3 +- upup/pkg/fi/cloudup/populate_cluster_spec.go | 2 +- .../fi/cloudup/populate_cluster_spec_test.go | 2 +- util/pkg/vfs/context.go | 6 ++++ 15 files changed, 67 insertions(+), 31 deletions(-) diff --git a/cmd/kops/util/factory.go b/cmd/kops/util/factory.go index c2df485834..8388417ea6 100644 --- a/cmd/kops/util/factory.go +++ b/cmd/kops/util/factory.go @@ -113,12 +113,13 @@ func (f *Factory) KopsClient() (simple.Clientset, error) { return nil, fmt.Errorf("error building kops API client: %v", err) } - f.clientset = &api.RESTClientset{ - BaseURL: &url.URL{ + f.clientset = api.NewRESTClientset( + f.VFSContext(), + &url.URL{ Scheme: "k8s", }, - KopsClient: kopsClient.Kops(), - } + kopsClient.Kops(), + ) } else { basePath, err := f.VFSContext().BuildVfsPath(registryPath) if err != nil { @@ -129,7 +130,7 @@ func (f *Factory) KopsClient() (simple.Clientset, error) { return nil, field.Invalid(field.NewPath("State Store"), registryPath, INVALID_STATE_ERROR) } - f.clientset = vfsclientset.NewVFSClientset(basePath) + f.clientset = vfsclientset.NewVFSClientset(f.VFSContext(), basePath) } if strings.HasPrefix(registryPath, "file://") { klog.Warning("The local filesystem state store is not functional for running clusters") diff --git a/examples/kops-api-example/apply.go b/examples/kops-api-example/apply.go index 44450b68fe..dbed836819 100644 --- a/examples/kops-api-example/apply.go +++ b/examples/kops-api-example/apply.go @@ -21,10 +21,11 @@ import ( "k8s.io/kops/pkg/client/simple/vfsclientset" "k8s.io/kops/upup/pkg/fi/cloudup" + "k8s.io/kops/util/pkg/vfs" ) func apply(ctx context.Context) error { - clientset := vfsclientset.NewVFSClientset(registryBase) + clientset := vfsclientset.NewVFSClientset(vfs.Context, registryBase) cluster, err := clientset.GetCluster(ctx, clusterName) if err != nil { diff --git a/examples/kops-api-example/up.go b/examples/kops-api-example/up.go index b21367a935..998d36bfdc 100644 --- a/examples/kops-api-example/up.go +++ b/examples/kops-api-example/up.go @@ -27,10 +27,11 @@ import ( "k8s.io/kops/upup/pkg/fi" "k8s.io/kops/upup/pkg/fi/cloudup" "k8s.io/kops/upup/pkg/fi/utils" + "k8s.io/kops/util/pkg/vfs" ) func up(ctx context.Context) error { - clientset := vfsclientset.NewVFSClientset(registryBase) + clientset := vfsclientset.NewVFSClientset(vfs.Context, registryBase) cluster := &api.Cluster{} cluster.ObjectMeta.Name = clusterName diff --git a/nodeup/pkg/model/kubelet_test.go b/nodeup/pkg/model/kubelet_test.go index bd08f038cd..2f689ad516 100644 --- a/nodeup/pkg/model/kubelet_test.go +++ b/nodeup/pkg/model/kubelet_test.go @@ -294,7 +294,7 @@ func mockedPopulateClusterSpec(ctx context.Context, c *kops.Cluster, cloud fi.Cl if err != nil { return nil, fmt.Errorf("error building vfspath: %v", err) } - clientset := vfsclientset.NewVFSClientset(basePath) + clientset := vfsclientset.NewVFSClientset(vfs.Context, basePath) return cloudup.PopulateClusterSpec(ctx, clientset, c, cloud, assetBuilder) } diff --git a/pkg/client/simple/api/clientset.go b/pkg/client/simple/api/clientset.go index cf7c0ff63b..85c27b85f8 100644 --- a/pkg/client/simple/api/clientset.go +++ b/pkg/client/simple/api/clientset.go @@ -38,10 +38,23 @@ import ( // RESTClientset is an implementation of clientset that uses a "real" generated REST client type RESTClientset struct { + vfsContext *vfs.VFSContext BaseURL *url.URL KopsClient kopsinternalversion.KopsInterface } +func NewRESTClientset(vfsContext *vfs.VFSContext, baseURL *url.URL, kopsClient kopsinternalversion.KopsInterface) *RESTClientset { + return &RESTClientset{ + vfsContext: vfsContext, + BaseURL: baseURL, + KopsClient: kopsClient, + } +} + +func (c *RESTClientset) VFSContext() *vfs.VFSContext { + return c.vfsContext +} + // GetCluster implements the GetCluster method of Clientset for a kubernetes-API state store func (c *RESTClientset) GetCluster(ctx context.Context, name string) (*kops.Cluster, error) { namespace := restNamespaceForClusterName(name) @@ -79,11 +92,11 @@ func (c *RESTClientset) UpdateCluster(ctx context.Context, cluster *kops.Cluster // ConfigBaseFor implements the ConfigBaseFor method of Clientset for a kubernetes-API state store func (c *RESTClientset) ConfigBaseFor(cluster *kops.Cluster) (vfs.Path, error) { if cluster.Spec.ConfigBase != "" { - return vfs.Context.BuildVfsPath(cluster.Spec.ConfigBase) + return c.VFSContext().BuildVfsPath(cluster.Spec.ConfigBase) } // URL for clusters looks like https:///apis/kops/v1alpha2/namespaces//clusters/ // We probably want to add a subresource for full resources - return vfs.Context.BuildVfsPath(c.BaseURL.String()) + return c.VFSContext().BuildVfsPath(c.BaseURL.String()) } // ListClusters implements the ListClusters method of Clientset for a kubernetes-API state store diff --git a/pkg/client/simple/clientset.go b/pkg/client/simple/clientset.go index 8f3882bfbb..0f8f0facf2 100644 --- a/pkg/client/simple/clientset.go +++ b/pkg/client/simple/clientset.go @@ -28,6 +28,9 @@ import ( ) type Clientset interface { + // VFSContext returns a VFSContext. + VFSContext() *vfs.VFSContext + // GetCluster reads a cluster by name GetCluster(ctx context.Context, name string) (*kops.Cluster, error) diff --git a/pkg/client/simple/vfsclientset/clientset.go b/pkg/client/simple/vfsclientset/clientset.go index 220b6b9b6b..ccf30770cf 100644 --- a/pkg/client/simple/vfsclientset/clientset.go +++ b/pkg/client/simple/vfsclientset/clientset.go @@ -34,11 +34,16 @@ import ( ) type VFSClientset struct { - basePath vfs.Path + vfsContext *vfs.VFSContext + basePath vfs.Path } var _ simple.Clientset = &VFSClientset{} +func (c *VFSClientset) VFSContext() *vfs.VFSContext { + return c.vfsContext +} + func (c *VFSClientset) clusters() *ClusterVFS { return newClusterVFS(c.basePath) } @@ -66,7 +71,7 @@ func (c *VFSClientset) ListClusters(ctx context.Context, options metav1.ListOpti // ConfigBaseFor implements the ConfigBaseFor method of simple.Clientset for a VFS-backed state store func (c *VFSClientset) ConfigBaseFor(cluster *kops.Cluster) (vfs.Path, error) { if cluster.Spec.ConfigBase != "" { - return vfs.Context.BuildVfsPath(cluster.Spec.ConfigBase) + return c.VFSContext().BuildVfsPath(cluster.Spec.ConfigBase) } return c.clusters().configBase(cluster.Name) } @@ -89,13 +94,13 @@ func (c *VFSClientset) SecretStore(cluster *kops.Cluster) (fi.SecretStore, error basedir := configBase.Join("secrets") return secrets.NewVFSSecretStore(cluster, basedir), nil } else { - storePath, err := vfs.Context.BuildVfsPath(cluster.Spec.SecretStore) + storePath, err := c.VFSContext().BuildVfsPath(cluster.Spec.SecretStore) return secrets.NewVFSSecretStore(cluster, storePath), err } } func (c *VFSClientset) KeyStore(cluster *kops.Cluster) (fi.CAStore, error) { - basedir, err := pkiPath(cluster) + basedir, err := c.pkiPath(cluster) if err != nil { return nil, err } @@ -106,14 +111,14 @@ func (c *VFSClientset) KeyStore(cluster *kops.Cluster) (fi.CAStore, error) { } func (c *VFSClientset) SSHCredentialStore(cluster *kops.Cluster) (fi.SSHCredentialStore, error) { - basedir, err := pkiPath(cluster) + basedir, err := c.pkiPath(cluster) if err != nil { return nil, err } return fi.NewVFSSSHCredentialStore(cluster, basedir), nil } -func pkiPath(cluster *kops.Cluster) (vfs.Path, error) { +func (c *VFSClientset) pkiPath(cluster *kops.Cluster) (vfs.Path, error) { if cluster.Spec.KeyStore == "" { configBase, err := registry.ConfigBase(cluster) if err != nil { @@ -121,7 +126,7 @@ func pkiPath(cluster *kops.Cluster) (vfs.Path, error) { } return configBase.Join("pki"), nil } else { - storePath, err := vfs.Context.BuildVfsPath(cluster.Spec.KeyStore) + storePath, err := c.VFSContext().BuildVfsPath(cluster.Spec.KeyStore) return storePath, err } } @@ -205,7 +210,7 @@ func (c *VFSClientset) DeleteCluster(ctx context.Context, cluster *kops.Cluster) if cluster.Spec.ServiceAccountIssuerDiscovery != nil { discoveryStore := cluster.Spec.ServiceAccountIssuerDiscovery.DiscoveryStore if discoveryStore != "" { - path, err := vfs.Context.BuildVfsPath(discoveryStore) + path, err := c.VFSContext().BuildVfsPath(discoveryStore) if err != nil { return err } @@ -223,7 +228,7 @@ func (c *VFSClientset) DeleteCluster(ctx context.Context, cluster *kops.Cluster) secretStore := cluster.Spec.SecretStore if secretStore != "" { - path, err := vfs.Context.BuildVfsPath(secretStore) + path, err := c.VFSContext().BuildVfsPath(secretStore) if err != nil { return err } @@ -235,7 +240,7 @@ func (c *VFSClientset) DeleteCluster(ctx context.Context, cluster *kops.Cluster) keyStore := cluster.Spec.KeyStore if keyStore != "" && keyStore != secretStore { - path, err := vfs.Context.BuildVfsPath(keyStore) + path, err := c.VFSContext().BuildVfsPath(keyStore) if err != nil { return err } @@ -253,9 +258,10 @@ func (c *VFSClientset) DeleteCluster(ctx context.Context, cluster *kops.Cluster) return DeleteAllClusterState(configBase) } -func NewVFSClientset(basePath vfs.Path) simple.Clientset { +func NewVFSClientset(vfsContext *vfs.VFSContext, basePath vfs.Path) simple.Clientset { vfsClientset := &VFSClientset{ - basePath: basePath, + vfsContext: vfsContext, + basePath: basePath, } return vfsClientset } diff --git a/pkg/client/simple/vfsclientset/clientset_test.go b/pkg/client/simple/vfsclientset/clientset_test.go index e21ded5bd4..b0c04e3e4e 100644 --- a/pkg/client/simple/vfsclientset/clientset_test.go +++ b/pkg/client/simple/vfsclientset/clientset_test.go @@ -24,6 +24,9 @@ import ( ) func TestSSHCredentialStoreOnConfigBase(t *testing.T) { + clientset := VFSClientset{ + vfsContext: vfs.Context, + } vfs.Context.ResetMemfsContext(true) configBase := "memfs://some/config/base" cluster := &kops.Cluster{ @@ -32,7 +35,7 @@ func TestSSHCredentialStoreOnConfigBase(t *testing.T) { }, } - p, err := pkiPath(cluster) + p, err := clientset.pkiPath(cluster) if err != nil { t.Errorf("Failed to create ssh path: %v", err) } @@ -46,6 +49,9 @@ func TestSSHCredentialStoreOnConfigBase(t *testing.T) { } func TestSSHCredentialStoreOnOwnCFS(t *testing.T) { + clientset := VFSClientset{ + vfsContext: vfs.Context, + } vfs.Context.ResetMemfsContext(true) configBase := "memfs://some/config/base" keyPath := "memfs://keys/some/config/base/pki" @@ -56,7 +62,7 @@ func TestSSHCredentialStoreOnOwnCFS(t *testing.T) { }, } - p, err := pkiPath(cluster) + p, err := clientset.pkiPath(cluster) if err != nil { t.Errorf("Failed to create ssh path: %v", err) } diff --git a/pkg/instancegroups/rollingupdate_os_test.go b/pkg/instancegroups/rollingupdate_os_test.go index 97b81fd33f..6578353f48 100644 --- a/pkg/instancegroups/rollingupdate_os_test.go +++ b/pkg/instancegroups/rollingupdate_os_test.go @@ -60,7 +60,7 @@ func getTestSetupOS(t *testing.T, ctx context.Context) (*RollingUpdateCluster, * assetBuilder := assets.NewAssetBuilder(inCluster.Spec.Assets, inCluster.Spec.KubernetesVersion, false) basePath, _ := vfs.Context.BuildVfsPath(inCluster.Spec.ConfigBase) - clientset := vfsclientset.NewVFSClientset(basePath) + clientset := vfsclientset.NewVFSClientset(vfs.Context, basePath) cluster, err := cloudup.PopulateClusterSpec(ctx, clientset, inCluster, mockcloud, assetBuilder) if err != nil { t.Fatalf("Failed to populate cluster spec: %v", err) diff --git a/upup/pkg/fi/cloudup/apply_cluster.go b/upup/pkg/fi/cloudup/apply_cluster.go index 8216212e7d..e9fbd5f1fd 100644 --- a/upup/pkg/fi/cloudup/apply_cluster.go +++ b/upup/pkg/fi/cloudup/apply_cluster.go @@ -266,7 +266,7 @@ func (c *ApplyClusterCmd) Run(ctx context.Context) error { cluster := c.Cluster - configBase, err := vfs.Context.BuildVfsPath(cluster.Spec.ConfigBase) + configBase, err := c.Clientset.VFSContext().BuildVfsPath(cluster.Spec.ConfigBase) if err != nil { return fmt.Errorf("error parsing config base %q: %v", cluster.Spec.ConfigBase, err) } diff --git a/upup/pkg/fi/cloudup/bootstrapchannelbuilder_test.go b/upup/pkg/fi/cloudup/bootstrapchannelbuilder_test.go index 024e156072..e36dcf7f92 100644 --- a/upup/pkg/fi/cloudup/bootstrapchannelbuilder_test.go +++ b/upup/pkg/fi/cloudup/bootstrapchannelbuilder_test.go @@ -122,7 +122,7 @@ func runChannelBuilderTest(t *testing.T, key string, addonManifests []string) { if err != nil { t.Errorf("error building vfspath: %v", err) } - clientset := vfsclientset.NewVFSClientset(basePath) + clientset := vfsclientset.NewVFSClientset(vfs.Context, basePath) secretStore, err := clientset.SecretStore(cluster) if err != nil { diff --git a/upup/pkg/fi/cloudup/new_cluster.go b/upup/pkg/fi/cloudup/new_cluster.go index fe4c42a0b4..76ecb678ec 100644 --- a/upup/pkg/fi/cloudup/new_cluster.go +++ b/upup/pkg/fi/cloudup/new_cluster.go @@ -41,7 +41,6 @@ import ( "k8s.io/kops/upup/pkg/fi/cloudup/gce" "k8s.io/kops/upup/pkg/fi/cloudup/openstack" "k8s.io/kops/util/pkg/architectures" - "k8s.io/kops/util/pkg/vfs" ) const ( @@ -352,7 +351,7 @@ func NewCluster(opt *NewClusterOptions, clientset simple.Clientset) (*NewCluster } if opt.DiscoveryStore != "" { - discoveryPath, err := vfs.Context.BuildVfsPath(opt.DiscoveryStore) + discoveryPath, err := clientset.VFSContext().BuildVfsPath(opt.DiscoveryStore) if err != nil { return nil, fmt.Errorf("error building DiscoveryStore for cluster: %v", err) } diff --git a/upup/pkg/fi/cloudup/populate_cluster_spec.go b/upup/pkg/fi/cloudup/populate_cluster_spec.go index 979bbc17b9..604960d404 100644 --- a/upup/pkg/fi/cloudup/populate_cluster_spec.go +++ b/upup/pkg/fi/cloudup/populate_cluster_spec.go @@ -159,7 +159,7 @@ func (c *populateClusterSpec) run(ctx context.Context, clientset simple.Clientse } } - configBase, err := vfs.Context.BuildVfsPath(cluster.Spec.ConfigBase) + configBase, err := clientset.VFSContext().BuildVfsPath(cluster.Spec.ConfigBase) if err != nil { return fmt.Errorf("error parsing ConfigBase %q: %v", cluster.Spec.ConfigBase, err) } diff --git a/upup/pkg/fi/cloudup/populate_cluster_spec_test.go b/upup/pkg/fi/cloudup/populate_cluster_spec_test.go index 56857184bd..3e9b737f70 100644 --- a/upup/pkg/fi/cloudup/populate_cluster_spec_test.go +++ b/upup/pkg/fi/cloudup/populate_cluster_spec_test.go @@ -115,7 +115,7 @@ func mockedPopulateClusterSpec(ctx context.Context, c *kopsapi.Cluster, cloud fi if err != nil { return nil, fmt.Errorf("error building vfspath: %v", err) } - clientset := vfsclientset.NewVFSClientset(basePath) + clientset := vfsclientset.NewVFSClientset(vfs.Context, basePath) return PopulateClusterSpec(ctx, clientset, c, cloud, assetBuilder) } diff --git a/util/pkg/vfs/context.go b/util/pkg/vfs/context.go index 88646c7f7a..397cb44eac 100644 --- a/util/pkg/vfs/context.go +++ b/util/pkg/vfs/context.go @@ -72,6 +72,12 @@ func NewVFSContext() *VFSContext { return v } +func NewTestingVFSContext() *VFSContext { + vfsContext := NewVFSContext() + vfsContext.ResetMemfsContext(true) + return vfsContext +} + func (v *VFSContext) WithGCSClient(gcsClient *storage.Service) *VFSContext { v.mutex.Lock() defer v.mutex.Unlock()