Skip to content

Commit 3bf1b79

Browse files
authored
Merge pull request kubernetes-sigs#453 from Trickybrain/Idempotency
Fix CSI Driver creating multiple filesystems per PVC
2 parents 8bd4b82 + 4b3abe2 commit 3bf1b79

17 files changed

+674
-472
lines changed

cmd/hooks/prestop_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,9 @@ import (
2121
"sigs.k8s.io/aws-fsx-csi-driver/pkg/driver"
2222
"testing"
2323

24-
"github.com/golang/mock/gomock"
2524
"github.com/stretchr/testify/assert"
2625
"github.com/stretchr/testify/require"
26+
"go.uber.org/mock/gomock"
2727
v1 "k8s.io/api/core/v1"
2828
driverMocks "sigs.k8s.io/aws-fsx-csi-driver/pkg/driver/mocks"
2929
)

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ require (
1212
github.com/onsi/gomega v1.35.1
1313
github.com/spf13/pflag v1.0.6
1414
github.com/stretchr/testify v1.10.0
15+
go.uber.org/mock v0.6.0
1516
google.golang.org/grpc v1.72.0
1617
k8s.io/api v0.33.0
1718
k8s.io/apimachinery v0.33.0

go.sum

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,8 @@ go.opentelemetry.io/otel/trace v1.35.0 h1:dPpEfJu1sDIqruz7BHFG3c7528f6ddfSWfFDVt
177177
go.opentelemetry.io/otel/trace v1.35.0/go.mod h1:WUk7DtFp1Aw2MkvqGdwiXYDZZNvA/1J8o6xRXLrIkyc=
178178
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
179179
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
180+
go.uber.org/mock v0.6.0 h1:hyF9dfmbgIX5EfOdasqLsWD6xqpNZlXblLB/Dbnwv3Y=
181+
go.uber.org/mock v0.6.0/go.mod h1:KiVJ4BqZJaMj4svdfmHM0AUx4NJYO8ZNpPnZn1Z+BBU=
180182
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
181183
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
182184
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
@@ -234,8 +236,8 @@ golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roY
234236
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
235237
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
236238
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
237-
golang.org/x/tools v0.26.0 h1:v/60pFQmzmT9ExmjDv2gGIfi3OqfKoEP6I5+umXlbnQ=
238-
golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0=
239+
golang.org/x/tools v0.36.0 h1:kWS0uv/zsvHEle1LbV5LE8QujrxB3wfQyxHfhOk0Qkg=
240+
golang.org/x/tools v0.36.0/go.mod h1:WBDiHKJK8YgLHlcQPYQzNCkUxUypCaa5ZegCVutKm+s=
239241
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
240242
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
241243
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=

pkg/cloud/cloud.go

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ type Cloud interface {
120120
DescribeFileSystem(ctx context.Context, fileSystemId string) (fs *FileSystem, err error)
121121
WaitForFileSystemAvailable(ctx context.Context, fileSystemId string) error
122122
WaitForFileSystemResize(ctx context.Context, fileSystemId string, resizeGiB int32) error
123+
FindFileSystemByVolumeName(ctx context.Context, volumeName string) (*FileSystem, error)
123124
}
124125

125126
type cloud struct {
@@ -445,3 +446,74 @@ func isBadRequestUpdateInProgress(err error) bool {
445446
var badRequest *types.BadRequest
446447
return errors.As(err, &badRequest) && strings.Contains(err.Error(), "Unable to perform the storage capacity update. There is an update already in progress.")
447448
}
449+
450+
func (c *cloud) FindFileSystemByVolumeName(ctx context.Context, volumeName string) (*FileSystem, error) {
451+
var nextToken *string
452+
const maxResults = 100
453+
454+
klog.V(4).InfoS("Searching for existing filesystem", "volumeName", volumeName)
455+
456+
// AWS FSx DescribeFileSystems API doesn't support filtering by tags,
457+
// so we paginate through all filesystems and filter client-side
458+
for {
459+
input := &fsx.DescribeFileSystemsInput{
460+
MaxResults: aws.Int32(maxResults),
461+
NextToken: nextToken,
462+
}
463+
464+
output, err := c.fsx.DescribeFileSystems(ctx, input)
465+
if err != nil {
466+
return nil, fmt.Errorf("failed to describe filesystems: %v", err)
467+
}
468+
469+
klog.V(5).InfoS("Checking batch of filesystems", "count", len(output.FileSystems))
470+
471+
// Search current batch
472+
for _, fs := range output.FileSystems {
473+
// Skip if filesystem is being deleted
474+
if fs.Lifecycle != types.FileSystemLifecycleAvailable &&
475+
fs.Lifecycle != types.FileSystemLifecycleCreating {
476+
continue
477+
}
478+
479+
// Check tags for volume name match
480+
for _, tag := range fs.Tags {
481+
if *tag.Key == VolumeNameTagKey && *tag.Value == volumeName {
482+
klog.V(2).InfoS("Found existing filesystem",
483+
"volumeName", volumeName,
484+
"fileSystemId", *fs.FileSystemId,
485+
"lifecycle", string(fs.Lifecycle))
486+
487+
mountName := "fsx"
488+
if fs.LustreConfiguration.MountName != nil {
489+
mountName = *fs.LustreConfiguration.MountName
490+
}
491+
492+
perUnitStorageThroughput := int32(0)
493+
if fs.LustreConfiguration.PerUnitStorageThroughput != nil {
494+
perUnitStorageThroughput = *fs.LustreConfiguration.PerUnitStorageThroughput
495+
}
496+
497+
return &FileSystem{
498+
FileSystemId: *fs.FileSystemId,
499+
CapacityGiB: *fs.StorageCapacity,
500+
DnsName: *fs.DNSName,
501+
MountName: mountName,
502+
StorageType: string(fs.StorageType),
503+
DeploymentType: string(fs.LustreConfiguration.DeploymentType),
504+
PerUnitStorageThroughput: perUnitStorageThroughput,
505+
}, nil
506+
}
507+
}
508+
}
509+
510+
// Check if more results exist
511+
if output.NextToken == nil {
512+
break
513+
}
514+
nextToken = output.NextToken
515+
}
516+
517+
klog.V(2).InfoS("No existing filesystem found", "volumeName", volumeName)
518+
return nil, ErrNotFound
519+
}

pkg/cloud/cloud_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ import (
2525
"github.com/aws/aws-sdk-go-v2/aws"
2626
"github.com/aws/aws-sdk-go-v2/service/fsx"
2727
"github.com/aws/aws-sdk-go-v2/service/fsx/types"
28-
"github.com/golang/mock/gomock"
28+
"go.uber.org/mock/gomock"
2929
"sigs.k8s.io/aws-fsx-csi-driver/pkg/cloud/mocks"
3030
)
3131

pkg/cloud/fakes.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,3 +105,12 @@ func (c *FakeCloudProvider) WaitForFileSystemAvailable(ctx context.Context, file
105105
func (c *FakeCloudProvider) WaitForFileSystemResize(ctx context.Context, fileSystemId string, resizeGiB int32) error {
106106
return nil
107107
}
108+
109+
func (c *FakeCloudProvider) FindFileSystemByVolumeName(ctx context.Context, volumeName string) (*FileSystem, error) {
110+
// Check if filesystem exists for this volume name
111+
fs, exists := c.fileSystems[volumeName]
112+
if exists {
113+
return fs, nil
114+
}
115+
return nil, ErrNotFound
116+
}

pkg/cloud/metadata_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ import (
2323
"testing"
2424

2525
"github.com/aws/aws-sdk-go-v2/feature/ec2/imds"
26-
"github.com/golang/mock/gomock"
26+
"go.uber.org/mock/gomock"
2727
v1 "k8s.io/api/core/v1"
2828
"k8s.io/apimachinery/pkg/runtime"
2929
"k8s.io/client-go/kubernetes"

pkg/cloud/mocks/mock_ec2metadata.go

Lines changed: 13 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/cloud/mocks/mock_fsx.go

Lines changed: 19 additions & 13 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/cloud/mocks/mock_metadata.go

Lines changed: 7 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)